Skip to content

#500: design-consensus 编排重设计 — phase9-router 唯一派发 owner,删 wakeup-runner 双重派发#501

Merged
loning merged 2 commits into
auto-refact-devfrom
refactor/iter500-issue-500
Jun 4, 2026
Merged

#500: design-consensus 编排重设计 — phase9-router 唯一派发 owner,删 wakeup-runner 双重派发#501
loning merged 2 commits into
auto-refact-devfrom
refactor/iter500-issue-500

Conversation

@loning
Copy link
Copy Markdown
Contributor

@loning loning commented Jun 3, 2026

摘要

落地 #500 design-consensus 编排重设计(r4 consensus,structural framing,no-new-schema)。

问题(headless P0 死锁): phase9-router 和 wakeup-runner 双重派发 design-consensus(ledger 42 次 helper_exit:3),reflector META_RESOLVED 在 headless 无 consumer(ledger handled=0) → 0-codex 死锁。

方案:

  • phase9-router 成为唯一 design-consensus worker intent owner,新增 META_RESOLVED:re-designmarker.round+1 三路 solver route
  • 删除 wakeup-runner 的 dispatch_design_consensus(消除双重派发)
  • wakeup-runner 只保留 closed action apply(drop→close、consensus→implement)
  • dispatch_consensus_implementation readiness 后转 crnd:phase:implementing
  • 无新增 schema(复用 HARNESS_SPAWN_INTENT)

范围

14 文件 +207/-282(删除为主):router.py +66、wakeup_runner.py -105、wakeup_plan.py、controller_actions.py +25、6 test 文件、CLAUDE/SKILL/runtime-exceptions 文档。

验证

verification_hints 全套(test_phase9_router_daemon test_wakeup_plan test_wakeup_runner test_controller_actions test_runtime_exception_authorization_sources test_skill_reference_anchors)— 471 tests OK

共识来源

design-consensus r1→r4(controller 手动驱动,daemon 停止期间),judge:META_JUDGE_DONE:consensus:structural:no-new-schema删除runner复派并固定re-design为marker.round+1。逐层收敛:r1 方向 → r2 schema → r3 no-new-schema+删runner → r4 re-design marker.round+1。

Closes #500

🤖 controller / codex-refactor-loop #500 落地

⟦AI:AUTO-LOOP⟧

…er 双重派发

落地 #500 r4 consensus(structural framing,no-new-schema):
- phase9-router 成为唯一 design-consensus worker intent owner,新增
  META_RESOLVED:re-design → marker.round+1 三路 solver route
- 删除 wakeup-runner 的 dispatch_design_consensus(消除双重派发 helper_exit:3)
- wakeup-runner 只保留 closed action apply(drop→close、consensus→implement)
- dispatch_consensus_implementation readiness 后转 crnd:phase:implementing
- 无新增 schema(复用 HARNESS_SPAWN_INTENT)

修复 headless P0:reflector META_RESOLVED 无 consumer + phase9-router/wakeup-runner
双重派发致 0-codex 死锁。14 文件 +207/-282;verification 471 tests 全绿。

共识由 controller 手动驱动 design-consensus r1→r4 达成(daemon 停止期间)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 architect review 通过: #396 边界收窄,无架构阻断

TL;DR


详细说明

我检查了实际三点 diff、CLAUDE.md / AGENTS.md#396 wakeup-runner 授权镜像、phase9-router 路由实现和 wakeup-plan 投影。结论是这次改动把 dispatch_design_consensuswakeup-runner 可执行 helper allowlist 中移除,并把 design-consensus completed-marker 证据降为 status-only;实际派发转回 phase9-router 这个 deterministic router。phase9-router 是 design-consensus 的窄路由 daemon,负责把固定 marker 转成 solver/judge spawn intent,不持 PR/issue 生命周期权限。

关键证据是 CLAUDE.md:40 要求 controller-runtime 例外必须 narrow allowlist、不能成为 generic lifecycle actor,并禁止把 .refactor-loop/host.env 当 host production SSOT。PR 后的 runtime-exceptions.md:204-208 仍要求 wakeup-runner 只消费 closed action projection、拒绝 generic command 字段;SKILL.md:511phase9/router.py:700-744META_RESOLVED:re-design 固定为 marker.round + 1 的 minimal/structural/delete solver triplet 继续路线,没有把判断权或通用命令面交给 runner。

没有发现新增 Refactor (...) / Old pattern / New principle 源码注释;环境里没有 HOST_ARCHITECTURE_GREP_CHECKSHOST_PROTO_POLICYEXTERNAL_REPOS,所以没有套用额外 host-specific 规则。


📎 完整 codex 原始输出(存档备查)
---
pr: 501
role: architect
head_sha: e733b1ac6b4c21520f16fa79aa09ad21e84b9fd2
verdict: approve
---

## Verdict
approve: no architectural concerns from the CLAUDE.md/AGENTS.md compliance angle; the PR narrows wakeup-runner authority and keeps the new design-consensus continuation on the phase9-router deterministic route.

## Evidence
- No reject findings. `CLAUDE.md:40` requires controller-runtime exceptions to stay narrow, durable, non-generic, and forbids `.refactor-loop/host.env` as host production SSOT; the PR removes `dispatch_design_consensus` from #396 wakeup-runner allowed actions while keeping #396 helper actions closed and validated.
- `skills/codex-refactor-loop/authorizations/runtime-exceptions.md:204-208` mirrors the narrowed #396 surface: `wakeup-runner` consumes only closed action projection, rejects generic command fields, and no longer lists `dispatch_design_consensus`.
- `skills/codex-refactor-loop/SKILL.md:511` and `skills/codex-refactor-loop/scripts/codex_refactor_loop/phase9/router.py:700-744` put `META_RESOLVED:re-design` on the router-owned source-adjacent solver-triplet route, matching the single-mainline/daemon-first boundary instead of reintroducing a wakeup-runner redispatch path.
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_plan.py:86-97` and `wakeup_runner.py:61-79` keep `dispatch_design_consensus` out of the executable #396 action/helper allowlists; router-owned completed-marker evidence is downgraded to status-only before runner application.
- Old/New pattern comment policy check: the net diff adds no new `Refactor (...)`, `Old pattern`, or `New principle` source comments; existing historical comments are unchanged context.
- No host-specific architecture grep checks, host proto policy, or external repo list were set in the environment, so no additional host-specific findings were applied.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:501:architect:approve

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 Tests review: reject,缺一个新增生命周期写失败分支测试

TL;DR

  • 这是什么: PR 501 的 tests 角度独立 review。
  • 现在到哪一步 / 结论是什么: reject,因为 dispatch_consensus_implementation 新增的 gh issue edit 失败路径没有测试覆盖。
  • controller 下一步: 补一个失败路径单测后重新跑 tests reviewer。

详细说明

dispatch_consensus_implementation 是把已达成共识的 issue 派发给实现 worker 的 controller helper;这次它新增了 _move_issue_to_implementing_phase,也就是先用 gh issue edit 把 issue 标签切到 implementing,再继续创建 worktree、渲染 prompt、写 HARNESS_SPAWN_INTENT。成功路径在 skills/codex-refactor-loop/scripts/test_controller_actions.py:837 已经断言了 gh issue edit 会被调用。

缺口是失败路径:skills/codex-refactor-loop/scripts/codex_refactor_loop/controller_actions.py:727 会在 phase transition 非 0 时直接返回,controller_actions.py:766 还会写 CONTROLLER_ACTION_BLOCKED:phase-transition:dispatch-consensus-implementation:issue:<N>。目前没有测试模拟 gh issue edit 返回非 0,并断言它会阻断 fresh_safe_worktreerender_templateHARNESS_SPAWN_INTENT。这是新增生命周期写动作的真实分支,不是 nice-to-have。

建议补一个 test_dispatch_consensus_implementation_phase_transition_failure_blocks_before_worktree:让 self.actions.gh 返回非 0,断言返回码被透传,pending event 写入,并用 AssertionError mock 确认 worktree/prompt/spawn 都没有发生。


📎 完整 codex 原始输出(存档备查)
---
pr: 501
role: tests
head_sha: e733b1ac6b4c21520f16fa79aa09ad21e84b9fd2
verdict: reject
---

## Verdict
Reject: test coverage misses the new lifecycle-write failure branch added to `dispatch_consensus_implementation`.

## Evidence
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/controller_actions.py:727` now calls `_move_issue_to_implementing_phase(number)` before creating the worktree, rendering the implement prompt, and appending the `HARNESS_SPAWN_INTENT`; `controller_actions.py:766` adds the helper that runs `gh issue edit`, appends `CONTROLLER_ACTION_BLOCKED:phase-transition:dispatch-consensus-implementation:issue:<N>` on nonzero exit, and returns the failed exit code.
- `skills/codex-refactor-loop/scripts/test_controller_actions.py:837` covers only the success path by asserting `gh issue edit` is called and implementation dispatch continues. The existing negative tests at `test_controller_actions.py:930` and `test_controller_actions.py:951` assert validation/readiness failures happen before any `gh` call, but there is no test where `gh issue edit` returns nonzero and dispatch must stop before `fresh_safe_worktree`, `render_template`, or `HARNESS_SPAWN_INTENT`.
- The rest of the design-consensus routing changes have behavior/source-regression coverage: `test_phase9_router_daemon.py:1835` covers reflector `META_RESOLVED:re-design` -> source-adjacent next-round solver intents, `test_phase9_router_daemon.py:1851` covers restart dedupe through the ledger, `test_wakeup_plan.py:1445` and `test_wakeup_plan.py:1455` cover router-owned completed markers becoming status-only, and `test_wakeup_runner.py:856` covers stale `dispatch_design_consensus` actions being rejected.

## What would change your verdict
Add a `test_dispatch_consensus_implementation_phase_transition_failure_blocks_before_worktree`-style test that makes `self.actions.gh` return nonzero for `issue edit`, asserts the return code is propagated, asserts the blocked pending event is written, and asserts `fresh_safe_worktree`, `render_template`, and `HARNESS_SPAWN_INTENT` do not run.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:501:tests:reject

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 Quality review 通过

TL;DR


详细说明

我看了三点 diff 和关键 touched files 的完整上下文。Phase9Router 是 design-consensus 的确定性路由器,新增的 _dispatch_reflector_routes 只处理 META_RESOLVED:re-design 并派发下一轮 solver triplet,入口在 router.py:315,实现集中在 router.py:700,没有把旧 runner redispatch 逻辑复制成第二套系统。

wakeup-runner 是 closed action 的机械 apply 执行器,这次在 wakeup_runner.py:61 从 allowlist 移除 dispatch_design_consensuswakeup_runner.py:77 也只保留通用 spawn_codex_harness_background 作为 spawn-batch action。wakeup_plan.py:2161_design_consensus_marker_is_router_owned 是判断 router-owned marker 的小 helper,调用点在 wakeup_plan.py:2130,命名表达了业务归属。controller_actions.py:766_move_issue_to_implementing_phase 有直接调用点 controller_actions.py:727,不是死代码。

验证方面,git diff --check origin/auto-refact-dev...origin/refactor/iter500-issue-500 通过。我也跑了相关窄测试集,但运行时是在当前 auto-refact-dev checkout 上,不是 PR head checkout;其中 2 个 test_phase9_router_daemon.py error 来自当前工作树仍读 ambient CONSENSUS_RND_HOST_ENV,而 PR head 对应行已经改成显式传 env={"REPO_ROOT": str(repo_root)},所以这不是本 PR 的 quality finding。


📎 完整 codex 原始输出(存档备查)
---
pr: 501
role: quality
head_sha: e733b1ac6b4c21520f16fa79aa09ad21e84b9fd2
verdict: approve
---

## Verdict
Approve: the PR is readable and focused, removes the old wakeup-runner design-consensus redispatch surface cleanly, and keeps the new router-owned continuation path small with reachable helpers and explicit route names.

## Evidence
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/phase9/router.py:315` calls the new `_dispatch_reflector_routes`, and `router.py:700` keeps the new `META_RESOLVED:re-design` path as one direct, named route rather than a broad redispatch helper.
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_runner.py:61` removes `dispatch_design_consensus` from `SUPPORTED_CONTROLLER_ACTIONS`, and `wakeup_runner.py:77` leaves only `spawn_codex_harness_background` in the spawn-batch action set; no dead private dispatch helper remains in the runner.
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_plan.py:86` removes `dispatch_design_consensus` from `RUNNER_NAMED_HELPER_ACTIONS`, and `wakeup_plan.py:2161` uses a small, business-named helper to mark router-owned design-consensus markers status-only.
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/controller_actions.py:727` reaches the new `_move_issue_to_implementing_phase` helper before worker intent creation, and the helper at `controller_actions.py:766` is narrowly named around the lifecycle phase transition it performs.
- I found no new single-implementer abstraction, commented-out code, filler self-doc comments, or unrelated drive-by cleanup that would change the quality verdict under `HOST_REFACTOR_COMMENT_POLICY=none`.
- Verification note: `git diff --check origin/auto-refact-dev...origin/refactor/iter500-issue-500` passed. A local narrow unittest run against the current `auto-refact-dev` checkout reported 2 `test_phase9_router_daemon.py` errors because the checked-out file still used ambient `CONSENSUS_RND_HOST_ENV`; the PR head version changes that constructor call to pass `env={"REPO_ROOT": str(repo_root)}`, so I did not treat that checkout mismatch as a PR quality finding.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:501:quality:approve

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 fix-codex 已补上 tests reject 要求

TL;DR


详细说明

本轮只有 tests reviewer 给出 reject。阻塞点是 dispatch_consensus_implementation,也就是把共识实现任务派给 worker 的 controller helper,在 gh issue edit 转入 implementing phase 失败时缺少负向测试。我在 skills/codex-refactor-loop/scripts/test_controller_actions.py:889 增加了对应测试:模拟 gh issue edit 返回非零,断言返回码透传、写入 blocked pending event,并断言不会创建 worktree、不会 render prompt、不会写 HARNESS_SPAWN_INTENTHARNESS_SPAWN_INTENT 是 controller 写给 daemon 的 worker 派发意图记录。

验证结果:编译通过;目标测试通过;完整 codex-refactor-loop unittest 在隔离 CONSENSUS_RND_HOST_ENV locator 后 1342 tests OK(skipped=1),sshx 13 tests OK。第一次按 prompt 字面继承 CONSENSUS_RND_HOST_ENV=.config/consensus-rnd/host.env 的 discover 失败,原因是该相对 locator 泄漏到测试临时 repo 后不可读;复跑时先 source host facts 再只 unset locator,测试通过。


📎 完整 codex 原始输出(存档备查)
# Fix report for PR 501 round 1

## Applied
- (A) skills/codex-refactor-loop/scripts/test_controller_actions.py:889: added a behavior test for `dispatch_consensus_implementation` when the issue phase-transition `gh issue edit` fails. The test propagates the nonzero return code, asserts `CONTROLLER_ACTION_BLOCKED:phase-transition:dispatch-consensus-implementation:issue:413` is written, and asserts `fresh_safe_worktree`, `render_template`, and `HARNESS_SPAWN_INTENT` do not run. Addresses reviewer:tests evidence #1.

## Rejected as false positive
- None.

## Blocked (cannot fix this round)
- None.

## Build status
- build: pass (`python3 -m compileall skills/codex-refactor-loop/scripts skills/sshx -q`)
- tests: pass
  - `python3 -m unittest skills/codex-refactor-loop/scripts/test_controller_actions.py -k phase_transition_failure` passed.
  - Initial prompt-literal discover command failed because exported `CONSENSUS_RND_HOST_ENV=.config/consensus-rnd/host.env` leaked into temporary test repos where that relative file is not readable; every reported traceback had `LoopContextError: CONSENSUS_RND_HOST_ENV is not a readable file: .config/consensus-rnd/host.env`.
  - Re-run with host facts sourced and only the locator unset passed: `source /Users/auric/consensus-rnd/.config/consensus-rnd/host.env; unset CONSENSUS_RND_HOST_ENV; python3 -m unittest discover -s skills/codex-refactor-loop/scripts -p "test_*.py" && python3 -m unittest discover -s skills/sshx/tests -p "test_*.py"` — codex-refactor-loop 1342 tests OK (skipped=1), sshx 13 tests OK.

## Recommendation for next round
- expect approve/merge: the only reject demand was covered directly, with no false positives or blocked items.

refactor self-doc: not applicable (HOST_REFACTOR_COMMENT_POLICY=none)

⟦AI:AUTO-LOOP⟧
FIX_DONE:501:round-1:applied-1:rejected-0:blocked-0

⟦AI:AUTO-LOOP⟧

…lure-branch test

tests reviewer reject:新增 label transition(gh issue edit→implementing)只测 success
path,缺 gh issue edit 返回 nonzero 时 dispatch stop before worktree/render/intent 的
failure-branch test。本 fix 补该测试。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 测试角度 review:approve

TL;DR


详细说明

这轮 diff 的测试覆盖到位。dispatch_consensus_implementation 是把 consensus 决策推进到 implementation 的 controller helper,测试覆盖了成功路径里的 issue phase label 更新、prompt/render 和 spawn-intent 输出,也覆盖了 label 更新失败时必须在 worktree/prompt 前阻断并写 blocked event。

phase9-router 是 design-consensus 的确定性路由器,测试覆盖了 META_RESOLVED:re-design 从 reflector 继续到下一轮 solver triplet,并验证 ledger 去重避免重启后重复派发。wakeup-planwakeup-runner 侧也有配套测试,确认旧的 dispatch_design_consensus redispatch 不再可执行,而是 status-only 或 fail-closed。未发现新增 [Skip]、manual category、测试节奏 sleep/delay,或把强断言改弱的情况。


📎 完整 codex 原始输出(存档备查)
---
pr: 501
role: tests
head_sha: c1009920cd7da68874817b758672b37b6b204a9c
verdict: approve
---

## Verdict
Test coverage and test quality are adequate for the diff.

## Evidence
- `skills/codex-refactor-loop/scripts/test_controller_actions.py:873` verifies the new `dispatch_consensus_implementation` phase transition adds the managed/implementing/auto label bundle before spawning implementation work, while preserving prompt rendering and spawn-intent output.
- `skills/codex-refactor-loop/scripts/test_controller_actions.py:889` covers the new failure branch: a failed issue phase transition blocks before worktree creation or prompt rendering and emits `CONTROLLER_ACTION_BLOCKED:phase-transition:dispatch-consensus-implementation:issue:413`.
- `skills/codex-refactor-loop/scripts/test_phase9_router_daemon.py:1845` covers the new `META_RESOLVED:re-design` router behavior by asserting source-adjacent `r5` solver triplet dispatch, exact ledger keys, and no accidental `r6` route.
- `skills/codex-refactor-loop/scripts/test_phase9_router_daemon.py:1851` covers restart idempotence for the new re-design route by asserting a fresh router tick does not duplicate dispatch intents.
- `skills/codex-refactor-loop/scripts/test_wakeup_plan.py:1445` and `skills/codex-refactor-loop/scripts/test_wakeup_plan.py:1455` cover the wakeup-plan contract change: router-owned design-consensus completed-marker evidence becomes status-only, loses runner authority, and keeps forbidden command fields out of projected actions.
- `skills/codex-refactor-loop/scripts/test_wakeup_runner.py:794` covers the removed wakeup-runner `dispatch_design_consensus` execution path by asserting stale redispatch actions fail closed as `unsupported_controller_action:dispatch_design_consensus` without launching a supervisor.
- Source-regression coverage is present in `skills/codex-refactor-loop/scripts/test_wakeup_plan.py:2255`, `skills/codex-refactor-loop/scripts/test_runtime_exception_authorization_sources.py`, and `skills/codex-refactor-loop/scripts/test_skill_reference_anchors.py`, locking the status-only/router-owned boundary and removal of `dispatch_design_consensus` from the #396 wakeup-runner allowlist.
- Diff scan found no added `[Skip]`/manual-test bypass, no test pacing `sleep`/`delay`, and no assertion weakening pattern that would reduce coverage quality.

## What would change your verdict (only if comment or reject)
N/A

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:501:tests:approve

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 Quality review approve

TL;DR


详细说明

我按 PR head c1009920cd7da68874817b758672b37b6b204a9c 查了三点: dispatch_design_consensus 是否还作为 wakeup-runner 可执行 helper 残留、phase9-router 新增的 META_RESOLVED:re-design 路由是否保持小而清晰、以及新增私有 helper 是否有调用点。

结论是代码质量角度可过。wakeup_runner.py 删除了平行的 design-consensus redispatch 分支;wakeup_plan.py 把 router-owned 设计共识 marker 统一降为 status-only;phase9/router.py_dispatch_reflector_routes 是约 45 行的单一路由,复用已有 ledger、terminal gate、source-open gate、prompt 和 spawn helper,没有再造第二套抽象。


📎 完整 codex 原始输出(存档备查)
---
pr: 501
role: quality
head_sha: c1009920cd7da68874817b758672b37b6b204a9c
verdict: approve
---

## Verdict
Approve: the PR simplifies ownership by deleting the wakeup-runner design-consensus redispatch path, keeps the new router continuation small and named in existing route vocabulary, and does not introduce quality-level dead code or over-engineering.

## Evidence
- skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_runner.py:61 removes `dispatch_design_consensus` from the supported runner action set, and the dispatch table at line 612 no longer carries a parallel private router implementation.
- skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_plan.py:86 removes `dispatch_design_consensus` from `RUNNER_NAMED_HELPER_ACTIONS`; completed design-consensus markers are normalized to status-only in `_close_projection_action` at line 2121 via `_design_consensus_marker_is_router_owned`, which is clearer than the prior terminal-only suppression helper.
- skills/codex-refactor-loop/scripts/codex_refactor_loop/phase9/router.py:700 adds `_dispatch_reflector_routes`, a 45-line route with explicit business names (`META_RESOLVED:re-design`, `redesign_to_next_solvers`, `target_round = marker.round + 1`) and reuses the existing ledger, terminal gate, source-open gate, prompt, and spawn helpers.
- skills/codex-refactor-loop/scripts/codex_refactor_loop/phase9/router.py:746 extends `_directly_handled` with the same `redesign_to_next_solvers` fallback keys, keeping fallback idempotency co-located with the other direct route checks instead of adding a second abstraction.
- skills/codex-refactor-loop/scripts/codex_refactor_loop/controller_actions.py:766 adds `_move_issue_to_implementing_phase`; it is private, directly called before worktree creation at line 727, and its name describes the lifecycle transition rather than using a generic helper name.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:501:quality:approve

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 Architect review approve: #501 未发现架构阻塞

TL;DR


详细说明

这次改动把 dispatch_design_consensuswakeup-runner 可执行动作里移除, 让 wakeup-plan 只把 design-consensus 完成 marker 投影成 status_only, 并把 META_RESOLVED:re-design 的下一轮 solver 派发收口到 phase9-router 的固定五路 allowlist。phase9-router 是 design-consensus 的窄路由 daemon, 这里只写 HARNESS_SPAWN_INTENT 语义意图, 不拿到任意 shell/git/gh 命令面。

我重点看了一个有副作用的点: dispatch_consensus_implementation 现在会在派实现 worker 前移动 issue phase label。它发生在已有 active-controller helper 内, 并且在 target/readiness 校验之后执行, 不是 phase9-router.refactor-loop/host.env 新增的通用生命周期权限。因此从 CLAUDE.md 的 narrow allowlist / no generic lifecycle actor 约束看, 不构成 reject。


📎 完整 codex 原始输出(存档备查)

pr: 501
role: architect
head_sha: c100992
verdict: approve

Verdict

approve - no architectural compliance concerns from the CLAUDE.md/AGENTS.md angle.

Evidence

  • No blocking issues found. CLAUDE.md:40 keeps daemon 完全自主运行:orchestrator 从交互 Claude Code 搬到 daemon+codex-worker(脱离 session 驱动全 loop) #396 narrowed to named helpers and removes dispatch_design_consensus; this matches the diff's removal of runner-side design-consensus dispatch authority and does not add a generic lifecycle actor.
  • skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_plan.py:86-97 removes dispatch_design_consensus from RUNNER_NAMED_HELPER_ACTIONS, and wakeup_plan.py:2129-2168 turns router-owned design-consensus markers into status_only actions with no_lifecycle_authority; this satisfies CLAUDE.md:40 "wakeup-plan ... not standalone authorization source" and avoids moving design-consensus routing into .refactor-loop/ as host production authority.
  • skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_runner.py:61-79 and wakeup_runner.py:354-376 no longer support dispatch_design_consensus; legacy/stray actions are blocked as unsupported rather than applied. This is deletion-first rather than a compatibility shim, matching CLAUDE.md:42 "废弃 skill、deprecated wrapper、.bak/.old/*.deprecated 直接删除".
  • skills/codex-refactor-loop/scripts/codex_refactor_loop/phase9/router.py:700-744 adds the reflector META_RESOLVED:re-design continuation only as router-owned solver HARNESS_SPAWN_INTENT dispatch after terminal/source-open gates, matching the documented direct-route allowlist in skills/codex-refactor-loop/SKILL.md:2026-2035 and the mirror at skills/codex-refactor-loop/authorizations/runtime-exceptions.md:313-316.
  • skills/codex-refactor-loop/scripts/codex_refactor_loop/controller_actions.py:693-775 adds an issue phase-label transition inside the existing active-controller helper dispatch_consensus_implementation after target/readiness validation and before worker spawn. This is a controller-owned helper path, not daemon-side label authority; it stays within CLAUDE.md:40 named helper boundaries and does not grant phase9-router label mutation.
  • Old/New pattern policy is satisfied for the net-new diff: I did not find new added refactor-history source comments. Existing Refactor (...) comments in unchanged surrounding text are pre-existing, not introduced by this PR.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:501:architect:approve

⟦AI:AUTO-LOOP⟧

@loning loning marked this pull request as ready for review June 4, 2026 05:31
@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

✅ review-gate 共识达成 → merge

  • r1: architect✓ / tests✗(缺 dispatch_consensus_implementation label-transition failure-branch test) / quality✓
  • fix r1: 补该 failure-branch test(test_controller_actions 91 tests OK)
  • r2(against c100992,含 fix): architect✓ tests✓ quality✓ → reject=0 → MERGE
  • CI: contract-tests✓ lint-advisory✓ manifest-version-sync✓ skill-degradation✓

合并 #500:phase9-router 唯一 design-consensus owner、删 wakeup-runner 双重派发、META_RESOLVED:re-design→marker.round+1、consensus→implementing label。修复 headless P0 双重派发 + reflector META_RESOLVED 无 consumer 死锁。

🤖 controller
⟦AI:AUTO-LOOP⟧

@loning loning merged commit 67bdb9e into auto-refact-dev Jun 4, 2026
4 checks passed
@loning loning deleted the refactor/iter500-issue-500 branch June 4, 2026 05:31
loning added a commit that referenced this pull request Jun 6, 2026
* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions 309 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r12: run_once 不再让 spawn-batch starve drain-only lifecycle — ready PR headless merge,backlog 能 drain

根因(已核实):wakeup_plan 每 tick 把 SPAWN actions(implement intent + design-consensus #495/#496/#490/#491/#418,index 0-5)排在 lifecycle review_gate(#480/#473/#402,index 6-8)之前;run_once 旧逻辑 `if applied_spawns>0 and not is_spawn_action: break` → 只要派了任一 spawn,首个 lifecycle 即 break 整 tick。design-consensus 几乎总有 spawn 活 → review_gate/merge 永远 starve → #473(approve/approve/comment → MERGE_WITH_COMMENTS,MERGEABLE+CI 绿)永不 merge,active 数永不下降。

修法(最小,核心 dispatch loop):
- 引入 consumes_spawn_budget = is_spawn_action or _uses_spawn_budget(action);超 budget 时 `continue`(不 break)以便仍能抵达后续 drain-only lifecycle。
- _uses_spawn_budget:dispatch_reviewers=True、review_gate 仅当决策为 FIX(会派 fix worker)=True;否则 review_gate(MERGE/MERGE_WITH_COMMENTS)、close 等 drain-only=False → 不占 spawn budget、floor 填满后仍被评估执行。
- 保留 r6 的 spawn launch-failure break/retry 与 dispatch_design_consensus no-intents skip-and-continue;真值表/head-binding/CI-green/mergeable 安全语义不变。

结果:每 tick 既用 spawn 填满 floor,又评估 merge/close 等 drain-only lifecycle,backlog 能 drain。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions+pr_checks 309 通过;新增 test_wakeup_runner_lifecycle_review_gate_not_starved_after_spawn_batch。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r13: 修 WakeupRunner._run_command 把 --repo 注入到 gh 子命令前致全部 gh 调用 malformed — review→merge 根因

根因(实测确认):_run_command 对所有 gh 命令在 full[1:1] 插 --repo(子命令之前)。gh 不接受 --repo 作 pre-subcommand 全局 flag,且 gh api 根本不吃 --repo(repo 在 URL):`gh --repo O/R api repos/O/R/pulls/473` → rc=1 "unknown flag: --repo"。于是 wakeup-runner 的每个 gh 调用都 malformed:CI 读(PrChecksProjection(runner=_run_command) 的 gh api pulls/check-runs)→ ci_unavailable:pull_api_failure;mergeability(gh pr view)→ mergeability_unavailable;live-state 等同理。→ review gate 永远读不到 CI/mergeable → #473(approve/approve/comment=MERGE_WITH_COMMENTS,绿)、#402#480 永不 headless 落地。r11 的 retry 只是重复同一 malformed 命令。直连 PrChecksProjection()/直连 gh 用的是 plain default runner(无注入)所以正常,掩盖了 bug。

最小修法:_run_command 仅对 `gh pr`/`gh issue` 注入 --repo,且放在子命令(及其 verb)之后的合法位置;`gh api` 完全不动;绝不 pre-subcommand 注入;已存在 --repo 则不重复。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+pr_checks+wakeup_plan+controller_actions 312 通过;新增 argv-shape 测试 + e2e(stub subprocess.run 拒绝 malformed `gh --repo ... api`,ready PR 仍 merge)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r14: managed draft PR ready-then-merge — review gate 不再硬挡 pr_draft

根因(r13 修好 gh 调用后浮现):review_gate 的 _review_gate_mergeability_error 把 isDraft=True 当 WAIT_OR_REDISPATCH:pr_draft 硬挡。但本 loop draft-until-consensus:PR 开为 draft 直到 review 共识,merge_pr 在决策 MERGE/MERGE_WITH_COMMENTS 时 ready-then-merge。于是绿 gate 的 managed draft(如 #473 approve/approve/comment)永远卡 pr_draft、永不 headless 落地。

最小修法:
- wakeup_runner:删除 mergeability 检查里的 isDraft→pr_draft 硬挡(仍挡 mergeable!=MERGEABLE,即 CONFLICTING/DIRTY)。
- controller_actions.merge_pr:对 live draft PR 先校验 crnd:lifecycle:managed 再 gh pr ready(非 managed draft 不 ready,写 CONTROLLER_ACTION_BLOCKED:target-not-managed 并返回 2);保留既有 ready-then-merge。
- 真值表/head-binding/CI-green/conflicting-blocks 安全语义不变;readying 仅限 managed PR。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan+pr_checks 316 通过;新增 managed-draft merge + 真实 plan→runner→controller ready-then-merge e2e + conflicting/非managed 安全用例。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #409: 移除 .refactor-loop/host.env runtime fallback,CONSENSUS_RND_HOST_ENV 为唯一 host fact locator(缺失 fail-closed);迁移依赖 legacy fallback 的 test fixture (#473)

* hotfix r15 (sshx 共识 B 之一): 统一 gh argv 构造到单一 build_gh_argv helper — 防 r13 类 --repo bug 复发

sshx 一致共识 B 的硬化第1步:把分散重复的 gh --repo 处理收口到 codex_refactor_loop/gh_invoke.py 的 build_gh_argv(slug, argv):gh api 永不加 --repo(repo 在 URL);gh pr/issue 仅在 subcommand 之后、缺失时加 --repo <slug>;绝不 pre-subcommand。wakeup_runner._run_command / ControllerActions.gh / PrChecksProjection 三处 API 调用全部改走该 helper,删除各自的内联 --repo 启发式。行为保持不变(含 r13 修复)。

验证:characterization + source-regression 锁在 test_gh_invoke.py(9 测试);controller 独立重跑 test_gh_invoke+pr_checks+wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan 326 通过;pr_checks 直跑 --help 兼容。

注:这是硬化(防复发),不直接提升并发;并发瓶颈在上游 implement→publish 阶段,接下来单独处理。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r16 (sshx 共识): 打通 implement→publish 解锁并发瓶颈 — markerless/stale implement 重派 + 安全门控发布

sshx codex-cli triplet 共识(minimal/structural/delete + meta-judge):10 个 design-solving issue 已达成共识但卡在 implement→publish(implement 早跑过却 markerless/未提交/过期 base/没 PR;dispatch_consensus_implementation 被 local_iter_branch 抑制、publish 被 verified_pr_head_unavailable 抑制)→ 无新可派工作 → 并发 ~1。

修法(wakeup_plan/wakeup_runner/controller_actions/git.py):
- success-aware 重派:implement 分支/worktree 存在但无 valid clean IMPLEMENT_DONE:ok marker(markerless/failed)或 base 过期 → 重派;fresh_safe_worktree 把 canonical worktree reset/recreate 到当前 origin/$INTEGRATION_BRANCH;仅 genuine in-flight / 已有干净 PR / 待发布 clean marker 才抑制。
- 发布门控(严防误发 stale/wrong-scope):publish_implementation_output 仅在 canonical identity(refactor/iter<issue>-<candidate> + worktree 实际分支匹配)+ fresh integration base(merge-base==origin/integration,过期 base block)+ managed open issue + 无重复 PR + 非空 scoped diff 时,commit→push→open PR→派 reviewers;否则 block。
- wakeup_plan 用 canonical_implementation_identity/single_linked_managed_issue/clean_scoped_diff 替代 verified_pr_head 抑制。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 330 通过。

已知待修(follow-up):worker 把 PR title/body/commit 文案改成英文,违反「GitHub artifact 中文」策略,下一 commit 恢复中文。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r17: fresh consensus-implement 重派前清除 terminal 非可发布 implement log — 让卡住的 implement 真正启动

承接 r16:r16 让 markerless/stale implement 重派(reset worktree),但旧的 EXIT=1/markerless implement log 仍占 spawn 的 target_log_absent 前置 → fresh implement 不启动(同一类「按存在抑制」,implement-spawn-log 层)。

修法(controller_actions,success-aware):fresh consensus-implementation dispatch 写 spawn intent 前,仅清除 terminal 非可发布 implement log(EXIT!=0 失败 / EXIT=0 无 IMPLEMENT_DONE:ok marker);保留 genuinely in-flight(无 EXIT)与 clean publish-ready(EXIT=0 + 干净 marker)log 不动。于是卡住的 markerless/failed implement 重派后能真正 launch、跑在 fresh base、产出干净 marker → r16 门控发布。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 333 通过。

设计说明:并发瓶颈用确定性逻辑修对(ready=clean EXIT=0+marker;parallel=scope_paths 不相交),不引入 LLM-in-loop 分发判断(daemon-first;sshx codex 三人组一致 revise:LLM 最多 shadow-mode,不入决策回路)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r18: implement-lifecycle 收敛为单一 success-aware 谓词 + runner 路径自清陈旧 log — headless 自愈,不再需手动清 log

承接 r16/r17(r17 把清 log 放进被抑制的 dispatch 路径,从没执行)。新增 implement_lifecycle.py 单一事实源 classify_implement_attempt → in_flight | publish_ready | redispatch,plan/runner/controller 共用:
- runner spawn-apply 路径 _spawn_log_suppresses_retry 仅在 in_flight|publish_ready 时抑制;redispatch(EXIT!=0/markerless/stale-base) 不抑制且 _clear_redispatchable_spawn_log 在 spawn 实际应用处清掉陈旧终态 log → fresh implement 真启动(修 r17 misplacement,免手动清)。
- publish 仅 publish_ready(clean IMPLEMENT_DONE:ok + canonical identity + fresh base + 非空 scoped diff);clean-marker 但 stale-base 改 redispatch 而非死锁(#421 edge)。
- 确定性逻辑(非 LLM-in-loop;daemon-first);merge-gate/#191/#322/#396 安全语义不变。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 339 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 phase9-router triplet-evidence-invalid 误判致 headless design-consensus wedge

solver prompt 注入的 issue source snapshot 含上一轮 design-consensus 的
audit-trail(peer solver log 路径)时,_peer_solver_reference_violation
扫描整个 prompt 误判为 peer-isolation 违规,fail-closed 拒派 meta-judge,
使所有 body 含历史 consensus 记录的 issue 永久 wedge。

修复:peer-isolation 扫描只覆盖 router-controlled 区域,剥离
'## Issue source snapshot' 到 '## Full solver template' 之间的 issue
作者内容;router header / solver template 注入的真实 peer 引用仍拦截。
加两个 behavior test 覆盖 snapshot-排除 与 router-区域-仍拦截。

dogfood headless 实测:reload 后 418/437/474/490/491/493/494/495 全部
恢复 solver→judge→consensus 自驱,#494 已自驱到 implement。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CLAUDE.md: 加 consensus-rnd:foundational-invariants sentinel block

dogfood bootstrap 的 check-project-rules probe 要求 PROJECT_RULES 含此
fixed-point block;缺失时 probe fail-closed 阻断 headless restart。内容
为 probe 生成的 canonical FI-001~007,镜像既有设计哲学,不引入新约束。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 markerless implement 致 publish 卡死的 headless gap

implement worker 干净退出(EXIT=0)但把 IMPLEMENT_DONE marker 只写进 run
artifact(runs/implement-issue-<id>.md)而非 log 末尾时(codex stdout marker
落点不可靠),completed_marker_actions 只扫 log marker → markerless → 不生成
publish action → design→implement→PR 链卡在 implement 后。实测 #421:EXIT=0
+ artifact 有 IMPLEMENT_DONE:issue-421:ok + 9 文件 staged,却无 PR、label 仍
停在 design-solving。

修复:对 clean-exit 的 implement-issue log,log markerless 时 fallback 读取
run artifact 末尾的 IMPLEMENT_DONE marker,复用 review verdict 已有的
artifact-first 模式。窄作用域(仅 implement-issue + clean-exit),配 2 个
behavior test;全套 wakeup_plan 138 tests green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 补全 markerless implement publish:revalidation 也读 run artifact marker

8aeea89 修了 wakeup_plan detection 端,但 wakeup-runner 的 source-marker
revalidation(_source_log_has_clean_marker)仍只扫 log,markerless implement
publish 仍被 reject(clean_exit_marker_missing)。补全:revalidation 对
clean-exit implement-issue log 在 log markerless 时 fallback 读
runs/implement-issue-<id>.md 的 marker,与 detection 端一致;配 behavior test,
全套 wakeup_runner 76 tests green。

注:dogfood 实测确认 markerless 是系统性病根(还影响 readiness 重派、review
verdict 等多处),应走系统性统一(见 #491 日志/observability 与后续 marker-reading
收口);本 commit 只补 implement publish 这条链。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 日志详细化:wakeup-runner tick 显示全状态计数 + 被掩盖的 blocked/skipped 详情

旧 _wakeup_tick_action 只看 results[0],一个 tick 处理多 action 时 blocked(如
publish 失败)被成功的 spawn 掩盖、完全不可见;graphql-backoff 固定显示误导的
'remaining=unknown'。dogfood 调试时这逼得每次翻 ledger 才知道真实发生了什么。

改:tick log 显示 [applied=N,blocked=M,...] 全状态计数 + 被掩盖的 blocked/skipped
具体 reason+action(graphql-backoff 作整-tick 门控单独报、去掉 unknown);dispatched
headline 保留。更新 test 反映可见性提升,全套 wakeup_runner 76 tests green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 补全 markerless implement 第三环:readiness 谓词读 run artifact marker

classify_implement_attempt(r18 单一 success-aware 谓词)只扫 log 找
IMPLEMENT_DONE:ok,markerless log(marker 落 artifact)→ redispatch:markerless →
readiness 不 suppress → 重派覆盖已完成工作(dogfood 实测 #421 重派 4 次、#493
IMPLEMENT_DONE:ok→重派→:partial 工作丢失)。

补全:markerless log 时 fallback 读 runs/implement-<cluster>.md 的
IMPLEMENT_DONE:ok,与 detection(8aeea89)/revalidation(dfacc64)一致。窄作用域 +
r17/r18 兼容:只接受 :ok,partial/失败/真 markerless(无 artifact)仍 redispatch
recovery — 现有 markerless-redispatch test(wakeup_plan/wakeup_runner/
controller_actions 共 304 tests)全绿,新增 2 behavior test。

至此 implement→PR 的 markerless 三环(detection/revalidation/readiness)打通;
review 链 markerless 与系统性统一抽象交 #499 共识。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #500: design-consensus 编排重设计 — phase9-router 唯一派发 owner,删 wakeup-runner 双重派发

落地 #500 r4 consensus(structural framing,no-new-schema):
- phase9-router 成为唯一 design-consensus worker intent owner,新增
  META_RESOLVED:re-design → marker.round+1 三路 solver route
- 删除 wakeup-runner 的 dispatch_design_consensus(消除双重派发 helper_exit:3)
- wakeup-runner 只保留 closed action apply(drop→close、consensus→implement)
- dispatch_consensus_implementation readiness 后转 crnd:phase:implementing
- 无新增 schema(复用 HARNESS_SPAWN_INTENT)

修复 headless P0:reflector META_RESOLVED 无 consumer + phase9-router/wakeup-runner
双重派发致 0-codex 死锁。14 文件 +207/-282;verification 471 tests 全绿。

共识由 controller 手动驱动 design-consensus r1→r4 达成(daemon 停止期间)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #501 fix r1: 补 dispatch_consensus_implementation label-transition failure-branch test

tests reviewer reject:新增 label transition(gh issue edit→implementing)只测 success
path,缺 gh issue edit 返回 nonzero 时 dispatch stop before worktree/render/intent 的
failure-branch test。本 fix 补该测试。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless 死锁:label 移除集只留 canonical crnd:*,删除历史 alias

gh issue/pr edit --remove-label 会因仓库不存在的 label 整条 rc=1 失败。
ISSUE_LABELS_REMOVE/PR_LABELS_REMOVE 含 cleanup_aliases(emoji/legacy 名),
仓库未维护这些历史 label,导致 _move_issue_to_implementing_phase 永久失败,
consensus→implement 派发卡死、wakeup_runner 0 codex 自驱死锁。

按 maintainer 指令删除历史 label 兼容(不再管历史标签):移除集只列
canonical crnd:* phase/human/stuck label。新增 source-regression 锁定
两集 canonical-only、无 alias。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 #500 回归:phase9-router 生产 ctx 丢失 GH_REPO_SLUG 致 design-consensus intake 全死

#500(e733b1a)把 Phase9Router.__init__ 的 ctx 构造从
`LoopContext.load(repo_root=repo_root)` 改成
`LoopContext.load(repo_root=repo_root, env={"REPO_ROOT": str(repo_root)})`。
受限 env 不读 os.environ,使 daemon(经 source host.env 启动)的 ctx
gh_repo_slug=None → `_open_design_consensus_issues` 第一行 fail-closed 返回 []
→ DesignConsensusIssueIntake 静默永不派 → headless 无法为任何 issue 启动
design-consensus;`_require_open_source_issue` 也因无 slug 失败(marker route
如 #490 redesign 卡在 phase9-source-state-unavailable)。

修复:revert 为 `LoopContext.load(repo_root=repo_root)`,读进程环境解析 host facts。
测试一律用 `Phase9Router(ctx=...)` 显式 ctx,不依赖受限 env;新增回归测试锁定
生产 repo_root 构造路径解析 GH_REPO_SLUG。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 加 STALE_REVIVAL_HOURS:>阈值未推进的 stuck implement 自动 re-trigger(env 可配,默认 3h)

headless 下 partial/failed/markerless 的 implement log 会让已排队的
dispatch-consensus-implementation spawn intent 永久卡在 runner 的
target_log_absent 前置(清 log 的 dispatch_consensus_implementation 又被
pending_implement_intent 抑制)→ stuck implement 不会自愈(如 #421/494/493/474/498
的 10h partial-wedge)。

新增 host-tunable STALE_REVIVAL_HOURS(默认 3,非正/非法回落 3h)。wakeup_plan
投影 implement spawn intent 时,若目标 implement log 是 redispatchable
(partial/failed/markerless/stale-base)且 mtime 已超阈值,清掉它 →
target_log_absent 通过 → implement 自动重派。安全闸:in-flight(无终止 EXIT)永不清、
publish-ready(:ok+diff)不清、age-gate 防误清刚跑完的。

env 已登记进 SKILL.md host env surface matrix + host.env.example;5 个 behavior
test + matrix↔example 对称测试覆盖。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 扩展 stale-revival 覆盖死 codex:in_flight 无 EXIT 且 >阈值 + 不在存活清单 也 re-trigger

最常见的 headless wedge 是 codex/supervisor 中途死亡(如 daemon 被 kill 截断),
log 永远停在 in_flight(无终止 EXIT)→ classify 永判 in_flight → 永不 redispatch。
之前只清 redispatchable(partial/failed/markerless)log,漏了这半边。

现在 _revive_stale_redispatchable_implement_log 在 log mtime 超阈值时,先按
redispatchable 清;否则若 classify 为 in_flight 且 monitor 存活清单里无该 log 的
活进程,则判定为死 worker 清掉。安全性:spawn-codex 的 no-output stall 窗口远小于
默认 3h,故 >阈值仍 in_flight 的 log 必是死 supervisor;再加 monitor 存活校验
双保险,绝不杀活 codex。新增 3 个 behavior test(死 codex revive / fresh 不碰 /
活进程不碰)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 加手动 trigger:consensus-rnd-cli revive-implements(立即 re-trigger 卡住的 implement,不等阈值)

_revive_stale_redispatchable_implement_log 加 force 参数:跳过 stale_revival_seconds()
age gate,但 in_flight log 在 force 下必须经 monitor 存活校验证明无活进程才清(绝不杀
正在跑的 codex)。新增 force_revive_stuck_implements() 扫所有 implement-issue-*.log
强制 revive,和新 CLI 命令 revive-implements(authority delete-log)。auto 路径
force=False 不变。新增 4 个 behavior test。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 env 泄漏:测试套件 import 时隔离 ambient host.env(worktree 里跑 TEST_CMD 不再假失败)

daemon spawn 的 implement worker 在 worktree 里跑完整 TEST_CMD 时,继承的相对
CONSENSUS_RND_HOST_ENV=.config/consensus-rnd/host.env 泄漏进 temp-repo
LoopContext.load(repo_root=tmp) → 解析成 tmp/.config/... 不存在 → 假
LoopContextError(实测 concurrency_monitor 48 + restart_daemons 23 + … ≈151 errors)
→ 全套永不绿 → implement 永远 :partial → 进不了 PR。

unittest discover 在 collection 阶段先 import 所有 test_*.py 再跑;新增
test_aaa_host_env_isolation.py(字母序最先)在 import 时 pop 掉 host 注入变量,
全套在任何测试 run 前即隔离。验证:full discover 设 locator 跑 → exit 0 全绿
(此前 同条件 151 errors);targeted before/after 证 48/23/1 errors → OK。
纯测试模块,不碰 production/daemon。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 markerless keystone:solver/judge marker 加 companion-artifact fallback

solver/judge codex 有时 EXIT=0 但 SOLVER_DONE/META_JUDGE_DONE marker 只落 run
artifact、没在 log 末尾,导致 phase9-router 判 triplet 不完整、永不派 judge,
design-consensus 轮卡死(实测 #505 r1 structural 214 次嵌入、0 次行首)。

把已有的 implement artifact-marker fallback 扩到 solver/judge:clean-exit log
末尾无独立 marker 时,从 companion run artifact runs/<log-stem>.md 兜底读。纯
additive(log 有 marker 时行为不变)、prefix-scoped、精确 filename regex、复用
安全的独立 marker 提取(不信嵌入/echo)。不削弱共识(仍要 3 marked solver +
judge,只让 marker 来源更稳健)。phase9/router.py + wakeup_plan.py + behavior +
source-regression tests;full suite 1367 green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 publish stale-base 无恢复 + 停 :ok churn:让 implementing 能发出 draft PR

implement :ok 但 worktree base 落后 origin/$INTEGRATION_BRANCH 时,publish 原本硬
block(publish_implementation_stale_base)且永不恢复;stale-revival 又把 stale-base
的 :ok implement 当 redispatchable 反复重派同一 stale worktree → 无限 churn 占满
floor、长时间零正式 PR(implement→首个 PR 永远开不出)。

改为:publish 前在 worktree merge origin/$INTEGRATION_BRANCH 恢复 base(冲突则
merge --abort + 明确 reason 交既有 resolver/re-dispatch);clean `:ok` 不再被
stale-revival churn(终态成功走 publish-with-recovery,不重跑);无 open PR 的 :ok
创建 draft PR(per #300 共识前 draft)+ Closes #N。controller 仍拥有 git topology,
worker 不 commit/push,不绕 review-gate/merge 真值表。controller_actions.py +
wakeup_plan.py + wakeup_runner.py + behavior/source-regression tests;full suite
1374 green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 markerless implement:EXIT=0+真diff 无干净 marker 时合成 publish 候选,止 stale-revival 空重派死循环

publish build/test 闸做安全网。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 publish 顺序 bug + merge 失败派 codex 兜底 resolver:先 commit worker diff 再 merge fresh base,真冲突不 wedge 改派 resolver,幂等续跑

空判据改 git diff HEAD;顺带修 wakeup_plan stale-suppression 同类 git diff 问题。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #504 (#519)

* 修 headless review-fix prompt 渲染不全:绑定全部 placeholder(PR_NUMBER/标题/轮次/分支/REVIEW_*_PATH 等),解锁 reject PR 的 fix→merge

之前 headless _dispatch_review_fix 只绑 FIX_OUTPUT_PATH,其余 ${} 未解析致 fix codex 读不到 reject 证据。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #496 (#520)

* 修 review-fix codex 派到 main 的 cd bug:改在 PR worktree 跑,worktree 缺失 fail-closed

之前 _dispatch_review_fix cd=repo_root → fix 改 main(污染 daemon checkout)且不落 PR 分支(reject PR 永不 merge)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #508 (#523)

* 修 wakeup-plan action 排序:review_gate/publish 排到新工作 spawn 前,解 spawn-budget 饿死→reject PR 可被 fix→merge

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CLAUDE.md 加宪法工程规则:异常必抛出+记可诊断日志严禁吞掉/静默;测试必断言真实行为禁无意义测试(maintainer 指令)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #503 (#521)

* 增加通用工程基本规则,明确面向对象设计要求及实现细则

* 实现 issue #514 (#524)

* 完善通用面向对象设计准则,增加核心原则与实现层细则

* 实现 issue #494 (#526)

* 实现 issue #517 (#528)

* 实现 issue #505 (#510)

* 实现 issue #505

* #510 fix r1:补 phase9-router 行为测试覆盖(应对 tests reviewer reject)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless FIX_DONE 不提交 fix 输出 gap:wakeup-runner 在 FIX_DONE re-review 前先 commit+push fix worktree

headless 下 fix codex 产出 FIX_DONE 但 worker 从不 commit,FIX_DONE 直接路由 dispatch_reviewers,
fix 输出永远留在 worktree 未提交,reviewers 永远审旧 head,reject 不收敛,阻断所有需 fix 轮的 PR
review→merge。镜像 interactive controller:FIX_DONE 源的 dispatch_reviewers 前,若 fix worktree
dirty 则 git add+commit+safe_push,clean 则 no-op。附 2 个 behavior test(dirty 提交/clean 跳过)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #491 (#531)

* 实现 issue #490 (#529)

* 实现 issue #490

* 实现 issue #490

* PR #529 review-fix output

* 实现 issue #499 (#512)

* 实现 issue #499

* PR #512 review-fix output

* 实现 issue #474 (#532)

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* PR #532 review-fix output

* 实现 issue #476 (#518)

* 实现 issue #476

* PR #518 review-fix output

* 实现 issue #509 (#527)

* 实现 issue #509

* 实现 issue #509

* spawn-claim recycle 改用 artifact-aware terminal marker:companion log 被 24h retention 删除后,已完成任务的 claim 仍可回收(读 runs/ artifact),不再永久阻断重派;running 任务无终止 marker 仍不回收(防 double-spawn)

* 实现 issue #421:发行前 clean-room 集成测试制度 (#534)

* 实现 issue #421

* rebase #421 onto fresh integration:解决 test_cli_command_router 冲突 + 校验

* 实现 issue #493:测试纪律修宪(behavior-first) (#535)

* 实现 issue #493

* rebase #493 onto fresh integration:解决冲突 + 校验

* PR #535 review-fix r1:addressed tests+quality reject(behavior-first test 调整)

* 实现 issue #506 (#536)

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* PR #536 review-fix output

* churn 根治:wakeup-plan 给 consensus-impl spawn-intent 套 open_closing_pr/terminal/in-flight 抑制(对齐 dispatch_consensus_implementation),已有 PR 的 issue 不再被重派 implement

* 实现 issue #507 (#525)

* 实现 issue #507

* 实现 issue #507

* PR #525 review-fix output

* 实现 issue #516 (#530)

* 实现 issue #516

* 实现 issue #516

* #530 fix r1:补 ManagedWorkSnapshot fetch-failure stale-cache fallback 行为测试(应对 tests reviewer reject)

* PR #530 review-fix output

* PR #530 review-fix r2:typed ManagedWorkItem projection(addresses architect 类型边界 reject + tests + contract-tests)

* PR #530 review-fix r3:anchor ManagedWorkSnapshot read surface in authorization mirror + cross-artifact source-regression(addresses architect governance reject)

* PR #530 review-fix r4:add canonical+legacy managed-label discovery regression test(addresses tests reject)

* 修复 worker marker reader 误判相同重复 marker 为冲突

codex 常把终止 marker 回显 2-3 次(含 diff + 前缀行),导致
read_worker_terminal_marker 返回 duplicate_or_conflicting,review 真值表
永不收敛、所有 headless review→merge 卡死。改为:相同重复 marker 折叠为
有效,仅当存在 2+ 个不同 marker 值才判 duplicate_or_conflicting。
覆盖 _last_final_marker / _sentinel_adjacent_marker /
_marker_from_companion_artifact,保留 malformed 与 foreign-prefix 检测。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reserve implementation PR for issue #537 (#540)

⟦AI:AUTO-LOOP⟧

* 实现 issue #511 (#522)

* 实现 issue #511

* PR #522 review-fix output

* PR #522 review-fix output

* 移除误入 PR 的 .refactor-loop 运行 artifact(architect r8 reject)

resolve-pr522-merge.md 是一次性合并解决 summary,属生成物,不应进 durable diff
(CLAUDE.md「生成物不当事实源」)。解决说明保留在 commit message / PR body。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复早期 PR reservation 崩溃(#511 回归,阻断所有 implement 派发)

_reserve_implementation_pr 用 worker 富正文路径开 reservation PR,但该文件在
reservation 时尚不存在 → FileNotFoundError(未被 except RuntimeError 捕获)→
wakeup-runner tick 崩溃 → 任何 consensus issue 无法 implement → loop P0 wedge。
修复:reservation 前若 body 缺失则写占位正文(## issue #N 实现 + Closes + sentinel,
publish 会拒占位逼 worker 产真正文);reservation 幂等(已有 open PR 直接返回;
已有 remote head 则 reset 到 integration + force-with-lease push);捕获 OSError。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reserve implementation PR for issue #543 (#544)

⟦AI:AUTO-LOOP⟧

* Reserve implementation PR for issue #541 (#546)

⟦AI:AUTO-LOOP⟧

* revert early-PR reservation(#507):不再开空占位 PR,publish 出真内容才开 PR

dispatch_consensus_implementation 不再 reserve/开 PR;publish_implementation_output
恢复 pre-#507 行为——implement 出非空 diff 才 commit+push+open_pr_with_label(用 worker
真 title/body,验证非占位);空 diff 不开 PR、不 merge、不关 issue。删除占位机制
(_reserve_implementation_pr / _placeholder_*),改 wakeup_plan/runner 的 early_pr_missing 投影。
根因:空占位 PR 被 reviewer 在 implement publish 前空合,假性关闭 #537/#541/#543。
全量套件 1496 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #542:删除 redispatch payload 冗余 head_sha (#547)

移除 review redispatch 的重复 head_sha payload

* hotfix: stale consensus-implement intent 指向已删 worktree 不再 suppress fresh re-dispatch

consensus_implementation_suppressed_reason 的 pending_implement_intent 分支增加 worktree 存在性
守卫(接入既有 _canonical_consensus_worktree_exists):仅当 stale pending intent 的 canonical
worktree 仍存在时才 suppress。revert early-PR reservation(#507)后,#537/#541/#543 的 pending
implement intent 指向已删除 worktree,旧逻辑 suppress fresh re-dispatch,而 wakeup-runner 不断把
stale intent spawn 进死 cd 致 os error 2 / EXIT=1 死循环,阻断 consensus→implement 自主链路。
现 worktree 缺失即放行 fresh dispatch 重建 worktree。

补 test_wakeup_plan(worktree 缺失不 suppress / worktree 存在仍 suppress)+ 更新
test_controller_actions 锁旧行为的 subTest(pending case 建 canonical worktree 以保留
reject-before-fresh_safe_worktree 意图)。全套件 1557 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: spawn-claim lock 持有者 pid 已死即可回收(自愈,防 cleared-log 永久 HELD)

_existing_claim_is_recyclable 增加 pid-liveness 回退:当 lock 记录的持有者 pid 已死(os.kill
pid 0 抛 ProcessLookupError)时即可回收,保留既有 terminal-marker 回收与 live-spawn 保护
(pid 存活+无 marker 仍不回收)+ metadata-mismatch fail-closed。根因:implement 失败(EXIT=1)
留 stale lock,dispatch_consensus_implementation 重派时清掉 log → #490 spawn-claim 只在 log 有
EXIT= 时回收 → cleared log 无 marker → 死进程 lock 无法回收 → SPAWN_CLAIM_HELD 永久死锁,
阻断 consensus→implement 重派(#537/#541/#543)。补 7 个 behavior test。全套件 1560 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: publish_implementation_output 接受 worker 已 commit 的实现 diff

_require_publish_implementation_diff 之前只看 git diff HEAD --quiet(未提交改动),
worker 一旦自己 commit(在自己分支上,隔离无害)工作区就 clean → 误判 no_diff → 不开 PR。
现改为:有未提交改动 OR HEAD 相对 integration base 有 committed delta(merge-base..HEAD 非空)
即视为有 diff 可发;_commit_publish_implementation_diff 在工作区已 clean(worker 已 commit)时
跳过提交返回成功,不再误报 publish_commit_failed。修 #541 类 worker-commit→no_diff→无 PR+
daemon 重复 dispatch。补 behavior test。codex 全套件 DISCOVER_STATUS:0 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #437: .refactor-loop 历史生成物与陈旧 worktree 的有界清理机制 (#548)

* #437: 新增 canonical RuntimeRetention owner,log-retention 降为一版 alias;清理覆盖 generated files+pending-events compaction+stale worktree;CLAUDE.md 加 #437 narrow carveout

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* hotfix: CONFLICTING managed review PR 的 stale-base 冲突自主 resolve

接线既有但孤儿的 prompts/rebase-resolve.md 进 headless 路径:managed review PR
mergeable=CONFLICTING(base 落后)时,controller 在 PR worktree 起 git merge
--no-commit --no-ff origin/<integration>——干净则直接 commit+push,有冲突则派
rebase-resolve codex(隔离 worktree 内解+stage,禁 commit/push),收到
REBASE_RESOLVE_DONE 后 controller commit + safe_push 仅推 PR head。结果再过 CI+
review-gate 把关。新增 dispatch_pr_rebase_resolve / commit_push_resolved_pr_rebase
(controller_actions)+ wakeup_plan 投影 + wakeup_runner 应用。

安全:只动 refactor/iter<N>-* PR 分支,显式 guard 拒碰 integration/review_base,
diff-filter=U 验未解冲突才 commit,任何 abort 路径 git merge --abort 留干净 worktree,
幂等(已含 base / 解析在飞则 NOOP)。修 stale-base churn 致 loop 永久停滞(一个 PR
合了其它全 CONFLICTING 无人解)的根因。codex 全套件 1589 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: rebase_resolve_actions 投影前 enrich live mergeability(修生产 gap)

自主-resolve 投影读 item.mergeable 前未 enrich,但生产 GhItem 来自 snapshot
mergeable 为空 → 永远 skip → CONFLICTING PR 不投影 dispatch_pr_rebase_resolve →
loop 仍停滞。复用同文件 _with_live_mergeability(review_evidence_redispatch_actions
已用同模式)。补 mergeable-为空-需-live-fetch 的回归测试(原测试 mock 了 mergeable
未覆盖此生产路径)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: dispatch_pr_rebase_resolve kind 进 EXECUTABLE_ACTION_KINDS(end-to-end 可执行)

_close_projection_action 的 else 分支默认 status_only=True;rebase action 的 kind
stale-base-conflicting-pr 不在 EXECUTABLE_ACTION_KINDS → 永远 status_only,runner 不
apply,CONFLICTING PR 永不自主 resolve。加该 kind(+ commit_push completion kind 如需)
进集合;controller_action 已在 RUNNER_NAMED_HELPER_ACTIONS 故随即保持 executable。补
端到端 wakeup-plan pipeline 测试(原测试只测 rebase_resolve_actions 单函数,漏了 closed-
action-projection 的 status_only 关卡)。codex 全套件 1593 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: rebase-resolve commit/dispatch 投影 gate 在实际 worktree merge 态(止 stale-marker 噪音)

commit_push_resolved_pr_rebase 之前只凭持久 REBASE_RESOLVE_DONE marker 投影,worktree
已 commit+push(#549)或 abort(#550/#551)后 marker 仍在 → 每 tick fail-closed 噪音 +
反复 0-codex(zero_streak 触警)+ stale marker 挡 #550/#551 fresh resolve。现 gate:仅当
worktree 真有 merge-in-progress(MERGE_HEAD)且无 unmerged 才投 executable commit_push;
否则不投。并让 worktree clean + 仍 CONFLICTING 的 PR 重新拿 executable dispatch_pr_rebase_resolve
(stale DONE marker 不再永久压制)。补端到端测试。codex 全套件通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec  (#549)

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec

* 修复 PR #549 review r3:#502 label-purge 适配当前 label 代码(contract-tests + architect/tests reject)

fix codex round-3 applied-4:对齐 #502 遗留 label 兼容层 purge 与近期新增 label 代码,
修 contract-tests 失败 + architect/tests reject。改 labels.py + SKILL.md + test_wakeup_plan.py。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless review_gate ci_failed 死锁:reject→FIX 移到 ci/mergeability 检查前

_review_gate_decision 之前 ci_error/mergeability 检查在 reject>0→FIX 之前 → CI 红的 PR
即使 reviewer reject 也返回 WAIT_OR_REDISPATCH:ci_failed 干等,而 CI 不修不会绿 → 死锁
(#548/#549 都中,需手动派 fix 破解)。把 reject>0→FIX 移到 ci/mergeability 检查前
(仍在 reviewer-validity/head 检查之后)→ reject 时即使 CI 红也自主派 fix(fix 同解 reject+CI)。
MERGE/MERGE_WITH_COMMENTS 判定完全不变(仍需 ci-green + mergeable + reject=0 + approve>=1),
无误合并风险。补 test_wakeup_runner 端到端测试(reject+ci-red→FIX;reject=0+ci-red 仍 WAIT;
happy path MERGE 不变;stale-head+reject 仍 WAIT)。full suite 1600 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修正 review_gate 顺序:mergeability 检查移到 reject→FIX 之前(CONFLICTING 不并发 review/fix)

上一修复(a125d19)把 reject→FIX 移到 ci+mergeability 前,破了 ci_failed 死锁但也让
CONFLICTING+reject 的 PR 路由到 FIX → 与独立的 dispatch_pr_rebase_resolve 并发跑同一
worktree(#550 出现 98-file mid-merge + reviewer 并发)。把 mergeability_error 检查移到
reject→FIX 之前:CONFLICTING→WAIT(先 rebase-resolve,不并发 review/fix);MERGEABLE+
CI红+reject→FIX(死锁修复保留);ci_error 仍在 reject→FIX 后(纯 CI 红无 reject 才 WAIT)。
MERGE 判定不变。test_wakeup_runner 90 OK(+conflicting 用例)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es (#550)

* 实现 issue #498

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es

* PR #550 review-fix output

* 新增 patrol-inspector 巡检 issue intake (#551)

* 实现 issue #541

* PR #551 review-fix output

* PR #551 review-fix output

* 修复 PR #551 contract-tests:对齐 patrol 第8 daemon + safe_push/sync_dev 测试 host.env

#551 patrol 新增 patrol_inspector_daemon(第8 daemon)→ test_anti_stop_restart 期望 7→8;
test_controller_lib_safe_push / test_sync_dev 补 CONSENSUS_RND_HOST_ENV host.env 设置
(代码按 host-config contract 需 host.env locator,rebase-resolve 丢了 base 新测试版本)。
断言未削弱(daemon 数断言强化为8)。full discovery 1634 OK + sshx 13 OK。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 PR #551 contract-tests(clean-env):e2e fixture 设 META_ESCALATION_STUCK_HOURS 隔离 de-dup 测试

test_batch_and_per_task_lock_do_not_duplicate_spawn 在 clean env(CI)下失败:#506 meta-
escalation 因 fixture mock 态被判 stuck 而 fire,产出 repository-stalled RunnerResult 污染
de-dup 断言(expected [] got [RunnerResult])。fixture host.env+env 设 META_ESCALATION_STUCK_
HOURS=999999 禁该测试的 meta-escalation,聚焦 de-dup 行为。断言未削弱。clean discovery 全过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 publish-gap:implement readiness 用 git status --porcelain 判 staged diff

原 classify_implement_attempt / wakeup_runner publish 前用 git diff --quiet 只检测 unstaged
改动;worker 正确 git add -A 后 staged diff 被误判 empty_scoped_diff,导致完成的 implement
(如 #553 干净 EXIT=0 + 885 行真实 staged diff + 有效 title/body artifacts)永远出不了 PR,
wakeup_runner 对 children 反复空转 re-dispatch。改为先 git status --porcelain 判 staged/
unstaged/untracked 任一即 publish-ready,只有真干净才 fallback git diff。publish-time 建 PR
路径不变(不重蹈 #507 early-PR 空 commit/placeholder 死锁)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 patrol_inspector daemon 启动崩溃:DaemonHeartbeatLease 用构造函数非 from_env

#551 patrol.py daemon 分支调 DaemonHeartbeatLease.from_env()(不存在的方法)→
AttributeError 启动即崩,daemon 从未成功跑起来。改为 DaemonHeartbeatLease(
"patrol_inspector_daemon", ctx.repo_root),与 closed_label_reconciler/wakeup_runner
一致,心跳文件名匹配 restart 助手期待的 patrol_inspector_daemon.ts。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 publish-gap 残留层:duplicate-marker log 读 companion artifact + 取代 superseded spawn intent

层2 残留:implement worker 把 IMPLEMENT_DONE:issue-N:ok 在 log 里 echo 多次→
worker_markers 返回 duplicate_or_conflicting_log_marker fail-closed→classifier 当
markerless 且不查 companion artifact→无 completed-marker action→无 publish→stale
harness-spawn-intent:dispatch-consensus-implementation:N 残留致 pending_implement_intent。

修:(1) classify_implement_attempt / completed_marker_actions 遇 duplicate marker 时
narrow 读 companion .refactor-loop/runs/implement-*.md(仅 implement log,仅末 30 行恰好
1 个 IMPLEMENT_DONE:ok 才接受);(2) suppress_publish_superseded_implementation_spawn_intents:
仅当某 issue 已有 executable publish_implementation_output 才把对应 dispatch-consensus-
implementation spawn intent 抑制为 status_only(implementation_ready_to_publish)。
不重蹈 #507 死锁:只在 publish 已 ready 后抑制 spawn(不漏派)、publish 仍全验证(不提前/
重复)、wakeup-runner/publish 授权口径不变。live 验证 #553 现投影 executable publish。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #555 (#557)

* 修复 publish-gap 第3层:wakeup_runner clean_exit revalidation 对 duplicate-marker log 复用 artifact-fallback

pubgap2 修了 plan 侧 duplicate-marker artifact-fallback,但 wakeup_runner 的
_source_log_has_clean_marker(clean_exit_source_marker 预条件 revalidation)仍用严格
reader,对 #553 duplicate IMPLEMENT_DONE echo 返回 clean_exit_marker_missing→阻 publish。
改为严格 reader 优先,仅当 duplicate_or_conflicting_log_marker + is_implement_log +
_implement_run_artifact_done_marker 精确匹配 projected marker 才 fallback。复用 plan 侧
同一 helper,不弱化安全门(reviewer/release/rebase/非 implement/其它 fail reason 保持严格)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 接 dispatch_remote_ci_fix 进 wakeup_runner:pipeline 自主修 ci-red(#396 内)

children review 通过但 contract-tests 红(改 restart/supervisor daemon 却没同步本地
TEST_CMD 屏蔽的 daemon-count 测试),wakeup_runner 缺 dispatch_remote_ci_fix 实现致
ci-red 永 status_only 不自主修。镜像既有 dispatch_reviewers + review-fix commit-push:
每失败 check 派一个 remote-ci-fix.md worker(无 commit 权),REMOTE_CI_FIX_DONE:<check>:ok
后 controller safe_push 推,:infra/:blocked 留 maintainer。durable retry cap=2 per
pr:head_sha:check(state/remote-ci-fix-attempts.json),超限 RETRY_CAP 停。在 #396
'dispatch remote-ci worker' 口径内,worker 无 lifecycle/commit 权,无新授权。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 wakeup_runner 单 helper 失败饿死全 tick:仅直接 spawn launch 失败才 break

run_once 对任何 spawn-budget blocked 且 reason 含 helper_exit:* 就 break 整 tick。rollup
PR #560(head rollup/<sha> 无 worktree)的 review-fix helper_exit:3(WORKTREE_MISSING)→
break → 饿死 #558/#561 的独立 ci-red 派发,致 runner ~30min noop 0 派发(0 codex)。
改为:仅直接 spawn_codex_harness_background launch 失败(is_spawn_action + _spawn_launch_failure)
才停扫描;blocked named helper(review_gate FIX / dispatch_remote_ci_fix)记录后 continue,
让同 tick 后面独立 PR 的 action 仍被处理。单 PR helper 失败不再阻塞全局派发。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 收紧无人唤醒与大 issue 分解授权测试 (#559)

* 实现 issue #556

* 实现 issue #556

* PR #559 review-fix output

* 修复 identical-duplicate terminal marker 被误判 conflicting:reader 容忍相同重复

remote-ci-fix worker echo REMOTE_CI_FIX_DONE:check:ok 两次→read_worker_terminal_marker
返回 duplicate_or_conflicting→runner 读不到→不 commit worker fix→撞 retry cap,#558 卡。
根因修(worker_markers._sentinel_adjacent_marker):无 sentinel-adjacent 但 tail 有 2+
standalone marker 全 identical 时返回该 marker。一次修 implement/ci-fix/未来所有 marker。
不弱化 conflicting:不同 marker 仍 fail,malformed 仍 fail,单非终止 marker 仍不终止。
不扩 #396;wakeup_runner 仍 revalidate clean_exit_source_marker 才 commit/push。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* rollup PR 自主化(maintainer-directive 2026-06-06):singleton + CI-only + 详细 body + auto-squash-merge

实现 maintainer 指令「rollup 只要ci过了就可以,不用review...绿了自动squash...默认自动,在env可配,只开一个rollup」:
- Singleton:已有 open rollup(head rollup/ + base review-base)时 force-with-lease 更新其 head 到当前
  integration SHA + 刷新 title/body;无则才新建,不增殖。
- CI-only:rollup PR 排除出 reviewer/review-fix/remote-ci-fix dispatch(不走 cluster 3-reviewer gate)。
- 详细 title/body:integration 领先 review-base 的 commit 数 + 范围 + commit 摘要(中文经 hex 编码守 source-EN-only)。
- Auto-squash-merge:host.env ROLLUP_AUTO_MERGE(默认 auto;manual 则等人工)。owner-gated + 仅 rollup PR
  narrow allowlist + exact-SHA required checks 全绿硬 gate(ReleaseRequiredChecksProjection)→ gh pr merge
  --squash --delete-branch;分支保护/host-policy 失败→WAIT 留人工不 force。所有失败写诊断 pending event。
- 授权双锚定:runtime-exceptions.md#rollup-autonomous-merge-2026-06-06 + SKILL.md + host.env surface matrix;
  durable artifact = maintainer-directives/2026-06-06。source-regression + behavior test 全覆盖。回归 1619 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
loning added a commit that referenced this pull request Jun 6, 2026
* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions 309 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r12: run_once 不再让 spawn-batch starve drain-only lifecycle — ready PR headless merge,backlog 能 drain

根因(已核实):wakeup_plan 每 tick 把 SPAWN actions(implement intent + design-consensus #495/#496/#490/#491/#418,index 0-5)排在 lifecycle review_gate(#480/#473/#402,index 6-8)之前;run_once 旧逻辑 `if applied_spawns>0 and not is_spawn_action: break` → 只要派了任一 spawn,首个 lifecycle 即 break 整 tick。design-consensus 几乎总有 spawn 活 → review_gate/merge 永远 starve → #473(approve/approve/comment → MERGE_WITH_COMMENTS,MERGEABLE+CI 绿)永不 merge,active 数永不下降。

修法(最小,核心 dispatch loop):
- 引入 consumes_spawn_budget = is_spawn_action or _uses_spawn_budget(action);超 budget 时 `continue`(不 break)以便仍能抵达后续 drain-only lifecycle。
- _uses_spawn_budget:dispatch_reviewers=True、review_gate 仅当决策为 FIX(会派 fix worker)=True;否则 review_gate(MERGE/MERGE_WITH_COMMENTS)、close 等 drain-only=False → 不占 spawn budget、floor 填满后仍被评估执行。
- 保留 r6 的 spawn launch-failure break/retry 与 dispatch_design_consensus no-intents skip-and-continue;真值表/head-binding/CI-green/mergeable 安全语义不变。

结果:每 tick 既用 spawn 填满 floor,又评估 merge/close 等 drain-only lifecycle,backlog 能 drain。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions+pr_checks 309 通过;新增 test_wakeup_runner_lifecycle_review_gate_not_starved_after_spawn_batch。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r13: 修 WakeupRunner._run_command 把 --repo 注入到 gh 子命令前致全部 gh 调用 malformed — review→merge 根因

根因(实测确认):_run_command 对所有 gh 命令在 full[1:1] 插 --repo(子命令之前)。gh 不接受 --repo 作 pre-subcommand 全局 flag,且 gh api 根本不吃 --repo(repo 在 URL):`gh --repo O/R api repos/O/R/pulls/473` → rc=1 "unknown flag: --repo"。于是 wakeup-runner 的每个 gh 调用都 malformed:CI 读(PrChecksProjection(runner=_run_command) 的 gh api pulls/check-runs)→ ci_unavailable:pull_api_failure;mergeability(gh pr view)→ mergeability_unavailable;live-state 等同理。→ review gate 永远读不到 CI/mergeable → #473(approve/approve/comment=MERGE_WITH_COMMENTS,绿)、#402#480 永不 headless 落地。r11 的 retry 只是重复同一 malformed 命令。直连 PrChecksProjection()/直连 gh 用的是 plain default runner(无注入)所以正常,掩盖了 bug。

最小修法:_run_command 仅对 `gh pr`/`gh issue` 注入 --repo,且放在子命令(及其 verb)之后的合法位置;`gh api` 完全不动;绝不 pre-subcommand 注入;已存在 --repo 则不重复。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+pr_checks+wakeup_plan+controller_actions 312 通过;新增 argv-shape 测试 + e2e(stub subprocess.run 拒绝 malformed `gh --repo ... api`,ready PR 仍 merge)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r14: managed draft PR ready-then-merge — review gate 不再硬挡 pr_draft

根因(r13 修好 gh 调用后浮现):review_gate 的 _review_gate_mergeability_error 把 isDraft=True 当 WAIT_OR_REDISPATCH:pr_draft 硬挡。但本 loop draft-until-consensus:PR 开为 draft 直到 review 共识,merge_pr 在决策 MERGE/MERGE_WITH_COMMENTS 时 ready-then-merge。于是绿 gate 的 managed draft(如 #473 approve/approve/comment)永远卡 pr_draft、永不 headless 落地。

最小修法:
- wakeup_runner:删除 mergeability 检查里的 isDraft→pr_draft 硬挡(仍挡 mergeable!=MERGEABLE,即 CONFLICTING/DIRTY)。
- controller_actions.merge_pr:对 live draft PR 先校验 crnd:lifecycle:managed 再 gh pr ready(非 managed draft 不 ready,写 CONTROLLER_ACTION_BLOCKED:target-not-managed 并返回 2);保留既有 ready-then-merge。
- 真值表/head-binding/CI-green/conflicting-blocks 安全语义不变;readying 仅限 managed PR。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan+pr_checks 316 通过;新增 managed-draft merge + 真实 plan→runner→controller ready-then-merge e2e + conflicting/非managed 安全用例。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #409: 移除 .refactor-loop/host.env runtime fallback,CONSENSUS_RND_HOST_ENV 为唯一 host fact locator(缺失 fail-closed);迁移依赖 legacy fallback 的 test fixture (#473)

* hotfix r15 (sshx 共识 B 之一): 统一 gh argv 构造到单一 build_gh_argv helper — 防 r13 类 --repo bug 复发

sshx 一致共识 B 的硬化第1步:把分散重复的 gh --repo 处理收口到 codex_refactor_loop/gh_invoke.py 的 build_gh_argv(slug, argv):gh api 永不加 --repo(repo 在 URL);gh pr/issue 仅在 subcommand 之后、缺失时加 --repo <slug>;绝不 pre-subcommand。wakeup_runner._run_command / ControllerActions.gh / PrChecksProjection 三处 API 调用全部改走该 helper,删除各自的内联 --repo 启发式。行为保持不变(含 r13 修复)。

验证:characterization + source-regression 锁在 test_gh_invoke.py(9 测试);controller 独立重跑 test_gh_invoke+pr_checks+wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan 326 通过;pr_checks 直跑 --help 兼容。

注:这是硬化(防复发),不直接提升并发;并发瓶颈在上游 implement→publish 阶段,接下来单独处理。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r16 (sshx 共识): 打通 implement→publish 解锁并发瓶颈 — markerless/stale implement 重派 + 安全门控发布

sshx codex-cli triplet 共识(minimal/structural/delete + meta-judge):10 个 design-solving issue 已达成共识但卡在 implement→publish(implement 早跑过却 markerless/未提交/过期 base/没 PR;dispatch_consensus_implementation 被 local_iter_branch 抑制、publish 被 verified_pr_head_unavailable 抑制)→ 无新可派工作 → 并发 ~1。

修法(wakeup_plan/wakeup_runner/controller_actions/git.py):
- success-aware 重派:implement 分支/worktree 存在但无 valid clean IMPLEMENT_DONE:ok marker(markerless/failed)或 base 过期 → 重派;fresh_safe_worktree 把 canonical worktree reset/recreate 到当前 origin/$INTEGRATION_BRANCH;仅 genuine in-flight / 已有干净 PR / 待发布 clean marker 才抑制。
- 发布门控(严防误发 stale/wrong-scope):publish_implementation_output 仅在 canonical identity(refactor/iter<issue>-<candidate> + worktree 实际分支匹配)+ fresh integration base(merge-base==origin/integration,过期 base block)+ managed open issue + 无重复 PR + 非空 scoped diff 时,commit→push→open PR→派 reviewers;否则 block。
- wakeup_plan 用 canonical_implementation_identity/single_linked_managed_issue/clean_scoped_diff 替代 verified_pr_head 抑制。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 330 通过。

已知待修(follow-up):worker 把 PR title/body/commit 文案改成英文,违反「GitHub artifact 中文」策略,下一 commit 恢复中文。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r17: fresh consensus-implement 重派前清除 terminal 非可发布 implement log — 让卡住的 implement 真正启动

承接 r16:r16 让 markerless/stale implement 重派(reset worktree),但旧的 EXIT=1/markerless implement log 仍占 spawn 的 target_log_absent 前置 → fresh implement 不启动(同一类「按存在抑制」,implement-spawn-log 层)。

修法(controller_actions,success-aware):fresh consensus-implementation dispatch 写 spawn intent 前,仅清除 terminal 非可发布 implement log(EXIT!=0 失败 / EXIT=0 无 IMPLEMENT_DONE:ok marker);保留 genuinely in-flight(无 EXIT)与 clean publish-ready(EXIT=0 + 干净 marker)log 不动。于是卡住的 markerless/failed implement 重派后能真正 launch、跑在 fresh base、产出干净 marker → r16 门控发布。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 333 通过。

设计说明:并发瓶颈用确定性逻辑修对(ready=clean EXIT=0+marker;parallel=scope_paths 不相交),不引入 LLM-in-loop 分发判断(daemon-first;sshx codex 三人组一致 revise:LLM 最多 shadow-mode,不入决策回路)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r18: implement-lifecycle 收敛为单一 success-aware 谓词 + runner 路径自清陈旧 log — headless 自愈,不再需手动清 log

承接 r16/r17(r17 把清 log 放进被抑制的 dispatch 路径,从没执行)。新增 implement_lifecycle.py 单一事实源 classify_implement_attempt → in_flight | publish_ready | redispatch,plan/runner/controller 共用:
- runner spawn-apply 路径 _spawn_log_suppresses_retry 仅在 in_flight|publish_ready 时抑制;redispatch(EXIT!=0/markerless/stale-base) 不抑制且 _clear_redispatchable_spawn_log 在 spawn 实际应用处清掉陈旧终态 log → fresh implement 真启动(修 r17 misplacement,免手动清)。
- publish 仅 publish_ready(clean IMPLEMENT_DONE:ok + canonical identity + fresh base + 非空 scoped diff);clean-marker 但 stale-base 改 redispatch 而非死锁(#421 edge)。
- 确定性逻辑(非 LLM-in-loop;daemon-first);merge-gate/#191/#322/#396 安全语义不变。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 339 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 phase9-router triplet-evidence-invalid 误判致 headless design-consensus wedge

solver prompt 注入的 issue source snapshot 含上一轮 design-consensus 的
audit-trail(peer solver log 路径)时,_peer_solver_reference_violation
扫描整个 prompt 误判为 peer-isolation 违规,fail-closed 拒派 meta-judge,
使所有 body 含历史 consensus 记录的 issue 永久 wedge。

修复:peer-isolation 扫描只覆盖 router-controlled 区域,剥离
'## Issue source snapshot' 到 '## Full solver template' 之间的 issue
作者内容;router header / solver template 注入的真实 peer 引用仍拦截。
加两个 behavior test 覆盖 snapshot-排除 与 router-区域-仍拦截。

dogfood headless 实测:reload 后 418/437/474/490/491/493/494/495 全部
恢复 solver→judge→consensus 自驱,#494 已自驱到 implement。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CLAUDE.md: 加 consensus-rnd:foundational-invariants sentinel block

dogfood bootstrap 的 check-project-rules probe 要求 PROJECT_RULES 含此
fixed-point block;缺失时 probe fail-closed 阻断 headless restart。内容
为 probe 生成的 canonical FI-001~007,镜像既有设计哲学,不引入新约束。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 markerless implement 致 publish 卡死的 headless gap

implement worker 干净退出(EXIT=0)但把 IMPLEMENT_DONE marker 只写进 run
artifact(runs/implement-issue-<id>.md)而非 log 末尾时(codex stdout marker
落点不可靠),completed_marker_actions 只扫 log marker → markerless → 不生成
publish action → design→implement→PR 链卡在 implement 后。实测 #421:EXIT=0
+ artifact 有 IMPLEMENT_DONE:issue-421:ok + 9 文件 staged,却无 PR、label 仍
停在 design-solving。

修复:对 clean-exit 的 implement-issue log,log markerless 时 fallback 读取
run artifact 末尾的 IMPLEMENT_DONE marker,复用 review verdict 已有的
artifact-first 模式。窄作用域(仅 implement-issue + clean-exit),配 2 个
behavior test;全套 wakeup_plan 138 tests green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 补全 markerless implement publish:revalidation 也读 run artifact marker

8aeea89 修了 wakeup_plan detection 端,但 wakeup-runner 的 source-marker
revalidation(_source_log_has_clean_marker)仍只扫 log,markerless implement
publish 仍被 reject(clean_exit_marker_missing)。补全:revalidation 对
clean-exit implement-issue log 在 log markerless 时 fallback 读
runs/implement-issue-<id>.md 的 marker,与 detection 端一致;配 behavior test,
全套 wakeup_runner 76 tests green。

注:dogfood 实测确认 markerless 是系统性病根(还影响 readiness 重派、review
verdict 等多处),应走系统性统一(见 #491 日志/observability 与后续 marker-reading
收口);本 commit 只补 implement publish 这条链。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 日志详细化:wakeup-runner tick 显示全状态计数 + 被掩盖的 blocked/skipped 详情

旧 _wakeup_tick_action 只看 results[0],一个 tick 处理多 action 时 blocked(如
publish 失败)被成功的 spawn 掩盖、完全不可见;graphql-backoff 固定显示误导的
'remaining=unknown'。dogfood 调试时这逼得每次翻 ledger 才知道真实发生了什么。

改:tick log 显示 [applied=N,blocked=M,...] 全状态计数 + 被掩盖的 blocked/skipped
具体 reason+action(graphql-backoff 作整-tick 门控单独报、去掉 unknown);dispatched
headline 保留。更新 test 反映可见性提升,全套 wakeup_runner 76 tests green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 补全 markerless implement 第三环:readiness 谓词读 run artifact marker

classify_implement_attempt(r18 单一 success-aware 谓词)只扫 log 找
IMPLEMENT_DONE:ok,markerless log(marker 落 artifact)→ redispatch:markerless →
readiness 不 suppress → 重派覆盖已完成工作(dogfood 实测 #421 重派 4 次、#493
IMPLEMENT_DONE:ok→重派→:partial 工作丢失)。

补全:markerless log 时 fallback 读 runs/implement-<cluster>.md 的
IMPLEMENT_DONE:ok,与 detection(8aeea89)/revalidation(dfacc64)一致。窄作用域 +
r17/r18 兼容:只接受 :ok,partial/失败/真 markerless(无 artifact)仍 redispatch
recovery — 现有 markerless-redispatch test(wakeup_plan/wakeup_runner/
controller_actions 共 304 tests)全绿,新增 2 behavior test。

至此 implement→PR 的 markerless 三环(detection/revalidation/readiness)打通;
review 链 markerless 与系统性统一抽象交 #499 共识。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #500: design-consensus 编排重设计 — phase9-router 唯一派发 owner,删 wakeup-runner 双重派发

落地 #500 r4 consensus(structural framing,no-new-schema):
- phase9-router 成为唯一 design-consensus worker intent owner,新增
  META_RESOLVED:re-design → marker.round+1 三路 solver route
- 删除 wakeup-runner 的 dispatch_design_consensus(消除双重派发 helper_exit:3)
- wakeup-runner 只保留 closed action apply(drop→close、consensus→implement)
- dispatch_consensus_implementation readiness 后转 crnd:phase:implementing
- 无新增 schema(复用 HARNESS_SPAWN_INTENT)

修复 headless P0:reflector META_RESOLVED 无 consumer + phase9-router/wakeup-runner
双重派发致 0-codex 死锁。14 文件 +207/-282;verification 471 tests 全绿。

共识由 controller 手动驱动 design-consensus r1→r4 达成(daemon 停止期间)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #501 fix r1: 补 dispatch_consensus_implementation label-transition failure-branch test

tests reviewer reject:新增 label transition(gh issue edit→implementing)只测 success
path,缺 gh issue edit 返回 nonzero 时 dispatch stop before worktree/render/intent 的
failure-branch test。本 fix 补该测试。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless 死锁:label 移除集只留 canonical crnd:*,删除历史 alias

gh issue/pr edit --remove-label 会因仓库不存在的 label 整条 rc=1 失败。
ISSUE_LABELS_REMOVE/PR_LABELS_REMOVE 含 cleanup_aliases(emoji/legacy 名),
仓库未维护这些历史 label,导致 _move_issue_to_implementing_phase 永久失败,
consensus→implement 派发卡死、wakeup_runner 0 codex 自驱死锁。

按 maintainer 指令删除历史 label 兼容(不再管历史标签):移除集只列
canonical crnd:* phase/human/stuck label。新增 source-regression 锁定
两集 canonical-only、无 alias。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 #500 回归:phase9-router 生产 ctx 丢失 GH_REPO_SLUG 致 design-consensus intake 全死

#500(e733b1a)把 Phase9Router.__init__ 的 ctx 构造从
`LoopContext.load(repo_root=repo_root)` 改成
`LoopContext.load(repo_root=repo_root, env={"REPO_ROOT": str(repo_root)})`。
受限 env 不读 os.environ,使 daemon(经 source host.env 启动)的 ctx
gh_repo_slug=None → `_open_design_consensus_issues` 第一行 fail-closed 返回 []
→ DesignConsensusIssueIntake 静默永不派 → headless 无法为任何 issue 启动
design-consensus;`_require_open_source_issue` 也因无 slug 失败(marker route
如 #490 redesign 卡在 phase9-source-state-unavailable)。

修复:revert 为 `LoopContext.load(repo_root=repo_root)`,读进程环境解析 host facts。
测试一律用 `Phase9Router(ctx=...)` 显式 ctx,不依赖受限 env;新增回归测试锁定
生产 repo_root 构造路径解析 GH_REPO_SLUG。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 加 STALE_REVIVAL_HOURS:>阈值未推进的 stuck implement 自动 re-trigger(env 可配,默认 3h)

headless 下 partial/failed/markerless 的 implement log 会让已排队的
dispatch-consensus-implementation spawn intent 永久卡在 runner 的
target_log_absent 前置(清 log 的 dispatch_consensus_implementation 又被
pending_implement_intent 抑制)→ stuck implement 不会自愈(如 #421/494/493/474/498
的 10h partial-wedge)。

新增 host-tunable STALE_REVIVAL_HOURS(默认 3,非正/非法回落 3h)。wakeup_plan
投影 implement spawn intent 时,若目标 implement log 是 redispatchable
(partial/failed/markerless/stale-base)且 mtime 已超阈值,清掉它 →
target_log_absent 通过 → implement 自动重派。安全闸:in-flight(无终止 EXIT)永不清、
publish-ready(:ok+diff)不清、age-gate 防误清刚跑完的。

env 已登记进 SKILL.md host env surface matrix + host.env.example;5 个 behavior
test + matrix↔example 对称测试覆盖。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 扩展 stale-revival 覆盖死 codex:in_flight 无 EXIT 且 >阈值 + 不在存活清单 也 re-trigger

最常见的 headless wedge 是 codex/supervisor 中途死亡(如 daemon 被 kill 截断),
log 永远停在 in_flight(无终止 EXIT)→ classify 永判 in_flight → 永不 redispatch。
之前只清 redispatchable(partial/failed/markerless)log,漏了这半边。

现在 _revive_stale_redispatchable_implement_log 在 log mtime 超阈值时,先按
redispatchable 清;否则若 classify 为 in_flight 且 monitor 存活清单里无该 log 的
活进程,则判定为死 worker 清掉。安全性:spawn-codex 的 no-output stall 窗口远小于
默认 3h,故 >阈值仍 in_flight 的 log 必是死 supervisor;再加 monitor 存活校验
双保险,绝不杀活 codex。新增 3 个 behavior test(死 codex revive / fresh 不碰 /
活进程不碰)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 加手动 trigger:consensus-rnd-cli revive-implements(立即 re-trigger 卡住的 implement,不等阈值)

_revive_stale_redispatchable_implement_log 加 force 参数:跳过 stale_revival_seconds()
age gate,但 in_flight log 在 force 下必须经 monitor 存活校验证明无活进程才清(绝不杀
正在跑的 codex)。新增 force_revive_stuck_implements() 扫所有 implement-issue-*.log
强制 revive,和新 CLI 命令 revive-implements(authority delete-log)。auto 路径
force=False 不变。新增 4 个 behavior test。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 env 泄漏:测试套件 import 时隔离 ambient host.env(worktree 里跑 TEST_CMD 不再假失败)

daemon spawn 的 implement worker 在 worktree 里跑完整 TEST_CMD 时,继承的相对
CONSENSUS_RND_HOST_ENV=.config/consensus-rnd/host.env 泄漏进 temp-repo
LoopContext.load(repo_root=tmp) → 解析成 tmp/.config/... 不存在 → 假
LoopContextError(实测 concurrency_monitor 48 + restart_daemons 23 + … ≈151 errors)
→ 全套永不绿 → implement 永远 :partial → 进不了 PR。

unittest discover 在 collection 阶段先 import 所有 test_*.py 再跑;新增
test_aaa_host_env_isolation.py(字母序最先)在 import 时 pop 掉 host 注入变量,
全套在任何测试 run 前即隔离。验证:full discover 设 locator 跑 → exit 0 全绿
(此前 同条件 151 errors);targeted before/after 证 48/23/1 errors → OK。
纯测试模块,不碰 production/daemon。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 markerless keystone:solver/judge marker 加 companion-artifact fallback

solver/judge codex 有时 EXIT=0 但 SOLVER_DONE/META_JUDGE_DONE marker 只落 run
artifact、没在 log 末尾,导致 phase9-router 判 triplet 不完整、永不派 judge,
design-consensus 轮卡死(实测 #505 r1 structural 214 次嵌入、0 次行首)。

把已有的 implement artifact-marker fallback 扩到 solver/judge:clean-exit log
末尾无独立 marker 时,从 companion run artifact runs/<log-stem>.md 兜底读。纯
additive(log 有 marker 时行为不变)、prefix-scoped、精确 filename regex、复用
安全的独立 marker 提取(不信嵌入/echo)。不削弱共识(仍要 3 marked solver +
judge,只让 marker 来源更稳健)。phase9/router.py + wakeup_plan.py + behavior +
source-regression tests;full suite 1367 green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 publish stale-base 无恢复 + 停 :ok churn:让 implementing 能发出 draft PR

implement :ok 但 worktree base 落后 origin/$INTEGRATION_BRANCH 时,publish 原本硬
block(publish_implementation_stale_base)且永不恢复;stale-revival 又把 stale-base
的 :ok implement 当 redispatchable 反复重派同一 stale worktree → 无限 churn 占满
floor、长时间零正式 PR(implement→首个 PR 永远开不出)。

改为:publish 前在 worktree merge origin/$INTEGRATION_BRANCH 恢复 base(冲突则
merge --abort + 明确 reason 交既有 resolver/re-dispatch);clean `:ok` 不再被
stale-revival churn(终态成功走 publish-with-recovery,不重跑);无 open PR 的 :ok
创建 draft PR(per #300 共识前 draft)+ Closes #N。controller 仍拥有 git topology,
worker 不 commit/push,不绕 review-gate/merge 真值表。controller_actions.py +
wakeup_plan.py + wakeup_runner.py + behavior/source-regression tests;full suite
1374 green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 markerless implement:EXIT=0+真diff 无干净 marker 时合成 publish 候选,止 stale-revival 空重派死循环

publish build/test 闸做安全网。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 publish 顺序 bug + merge 失败派 codex 兜底 resolver:先 commit worker diff 再 merge fresh base,真冲突不 wedge 改派 resolver,幂等续跑

空判据改 git diff HEAD;顺带修 wakeup_plan stale-suppression 同类 git diff 问题。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #504 (#519)

* 修 headless review-fix prompt 渲染不全:绑定全部 placeholder(PR_NUMBER/标题/轮次/分支/REVIEW_*_PATH 等),解锁 reject PR 的 fix→merge

之前 headless _dispatch_review_fix 只绑 FIX_OUTPUT_PATH,其余 ${} 未解析致 fix codex 读不到 reject 证据。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #496 (#520)

* 修 review-fix codex 派到 main 的 cd bug:改在 PR worktree 跑,worktree 缺失 fail-closed

之前 _dispatch_review_fix cd=repo_root → fix 改 main(污染 daemon checkout)且不落 PR 分支(reject PR 永不 merge)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #508 (#523)

* 修 wakeup-plan action 排序:review_gate/publish 排到新工作 spawn 前,解 spawn-budget 饿死→reject PR 可被 fix→merge

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CLAUDE.md 加宪法工程规则:异常必抛出+记可诊断日志严禁吞掉/静默;测试必断言真实行为禁无意义测试(maintainer 指令)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #503 (#521)

* 增加通用工程基本规则,明确面向对象设计要求及实现细则

* 实现 issue #514 (#524)

* 完善通用面向对象设计准则,增加核心原则与实现层细则

* 实现 issue #494 (#526)

* 实现 issue #517 (#528)

* 实现 issue #505 (#510)

* 实现 issue #505

* #510 fix r1:补 phase9-router 行为测试覆盖(应对 tests reviewer reject)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless FIX_DONE 不提交 fix 输出 gap:wakeup-runner 在 FIX_DONE re-review 前先 commit+push fix worktree

headless 下 fix codex 产出 FIX_DONE 但 worker 从不 commit,FIX_DONE 直接路由 dispatch_reviewers,
fix 输出永远留在 worktree 未提交,reviewers 永远审旧 head,reject 不收敛,阻断所有需 fix 轮的 PR
review→merge。镜像 interactive controller:FIX_DONE 源的 dispatch_reviewers 前,若 fix worktree
dirty 则 git add+commit+safe_push,clean 则 no-op。附 2 个 behavior test(dirty 提交/clean 跳过)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #491 (#531)

* 实现 issue #490 (#529)

* 实现 issue #490

* 实现 issue #490

* PR #529 review-fix output

* 实现 issue #499 (#512)

* 实现 issue #499

* PR #512 review-fix output

* 实现 issue #474 (#532)

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* PR #532 review-fix output

* 实现 issue #476 (#518)

* 实现 issue #476

* PR #518 review-fix output

* 实现 issue #509 (#527)

* 实现 issue #509

* 实现 issue #509

* spawn-claim recycle 改用 artifact-aware terminal marker:companion log 被 24h retention 删除后,已完成任务的 claim 仍可回收(读 runs/ artifact),不再永久阻断重派;running 任务无终止 marker 仍不回收(防 double-spawn)

* 实现 issue #421:发行前 clean-room 集成测试制度 (#534)

* 实现 issue #421

* rebase #421 onto fresh integration:解决 test_cli_command_router 冲突 + 校验

* 实现 issue #493:测试纪律修宪(behavior-first) (#535)

* 实现 issue #493

* rebase #493 onto fresh integration:解决冲突 + 校验

* PR #535 review-fix r1:addressed tests+quality reject(behavior-first test 调整)

* 实现 issue #506 (#536)

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* PR #536 review-fix output

* churn 根治:wakeup-plan 给 consensus-impl spawn-intent 套 open_closing_pr/terminal/in-flight 抑制(对齐 dispatch_consensus_implementation),已有 PR 的 issue 不再被重派 implement

* 实现 issue #507 (#525)

* 实现 issue #507

* 实现 issue #507

* PR #525 review-fix output

* 实现 issue #516 (#530)

* 实现 issue #516

* 实现 issue #516

* #530 fix r1:补 ManagedWorkSnapshot fetch-failure stale-cache fallback 行为测试(应对 tests reviewer reject)

* PR #530 review-fix output

* PR #530 review-fix r2:typed ManagedWorkItem projection(addresses architect 类型边界 reject + tests + contract-tests)

* PR #530 review-fix r3:anchor ManagedWorkSnapshot read surface in authorization mirror + cross-artifact source-regression(addresses architect governance reject)

* PR #530 review-fix r4:add canonical+legacy managed-label discovery regression test(addresses tests reject)

* 修复 worker marker reader 误判相同重复 marker 为冲突

codex 常把终止 marker 回显 2-3 次(含 diff + 前缀行),导致
read_worker_terminal_marker 返回 duplicate_or_conflicting,review 真值表
永不收敛、所有 headless review→merge 卡死。改为:相同重复 marker 折叠为
有效,仅当存在 2+ 个不同 marker 值才判 duplicate_or_conflicting。
覆盖 _last_final_marker / _sentinel_adjacent_marker /
_marker_from_companion_artifact,保留 malformed 与 foreign-prefix 检测。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reserve implementation PR for issue #537 (#540)

⟦AI:AUTO-LOOP⟧

* 实现 issue #511 (#522)

* 实现 issue #511

* PR #522 review-fix output

* PR #522 review-fix output

* 移除误入 PR 的 .refactor-loop 运行 artifact(architect r8 reject)

resolve-pr522-merge.md 是一次性合并解决 summary,属生成物,不应进 durable diff
(CLAUDE.md「生成物不当事实源」)。解决说明保留在 commit message / PR body。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复早期 PR reservation 崩溃(#511 回归,阻断所有 implement 派发)

_reserve_implementation_pr 用 worker 富正文路径开 reservation PR,但该文件在
reservation 时尚不存在 → FileNotFoundError(未被 except RuntimeError 捕获)→
wakeup-runner tick 崩溃 → 任何 consensus issue 无法 implement → loop P0 wedge。
修复:reservation 前若 body 缺失则写占位正文(## issue #N 实现 + Closes + sentinel,
publish 会拒占位逼 worker 产真正文);reservation 幂等(已有 open PR 直接返回;
已有 remote head 则 reset 到 integration + force-with-lease push);捕获 OSError。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reserve implementation PR for issue #543 (#544)

⟦AI:AUTO-LOOP⟧

* Reserve implementation PR for issue #541 (#546)

⟦AI:AUTO-LOOP⟧

* revert early-PR reservation(#507):不再开空占位 PR,publish 出真内容才开 PR

dispatch_consensus_implementation 不再 reserve/开 PR;publish_implementation_output
恢复 pre-#507 行为——implement 出非空 diff 才 commit+push+open_pr_with_label(用 worker
真 title/body,验证非占位);空 diff 不开 PR、不 merge、不关 issue。删除占位机制
(_reserve_implementation_pr / _placeholder_*),改 wakeup_plan/runner 的 early_pr_missing 投影。
根因:空占位 PR 被 reviewer 在 implement publish 前空合,假性关闭 #537/#541/#543。
全量套件 1496 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #542:删除 redispatch payload 冗余 head_sha (#547)

移除 review redispatch 的重复 head_sha payload

* hotfix: stale consensus-implement intent 指向已删 worktree 不再 suppress fresh re-dispatch

consensus_implementation_suppressed_reason 的 pending_implement_intent 分支增加 worktree 存在性
守卫(接入既有 _canonical_consensus_worktree_exists):仅当 stale pending intent 的 canonical
worktree 仍存在时才 suppress。revert early-PR reservation(#507)后,#537/#541/#543 的 pending
implement intent 指向已删除 worktree,旧逻辑 suppress fresh re-dispatch,而 wakeup-runner 不断把
stale intent spawn 进死 cd 致 os error 2 / EXIT=1 死循环,阻断 consensus→implement 自主链路。
现 worktree 缺失即放行 fresh dispatch 重建 worktree。

补 test_wakeup_plan(worktree 缺失不 suppress / worktree 存在仍 suppress)+ 更新
test_controller_actions 锁旧行为的 subTest(pending case 建 canonical worktree 以保留
reject-before-fresh_safe_worktree 意图)。全套件 1557 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: spawn-claim lock 持有者 pid 已死即可回收(自愈,防 cleared-log 永久 HELD)

_existing_claim_is_recyclable 增加 pid-liveness 回退:当 lock 记录的持有者 pid 已死(os.kill
pid 0 抛 ProcessLookupError)时即可回收,保留既有 terminal-marker 回收与 live-spawn 保护
(pid 存活+无 marker 仍不回收)+ metadata-mismatch fail-closed。根因:implement 失败(EXIT=1)
留 stale lock,dispatch_consensus_implementation 重派时清掉 log → #490 spawn-claim 只在 log 有
EXIT= 时回收 → cleared log 无 marker → 死进程 lock 无法回收 → SPAWN_CLAIM_HELD 永久死锁,
阻断 consensus→implement 重派(#537/#541/#543)。补 7 个 behavior test。全套件 1560 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: publish_implementation_output 接受 worker 已 commit 的实现 diff

_require_publish_implementation_diff 之前只看 git diff HEAD --quiet(未提交改动),
worker 一旦自己 commit(在自己分支上,隔离无害)工作区就 clean → 误判 no_diff → 不开 PR。
现改为:有未提交改动 OR HEAD 相对 integration base 有 committed delta(merge-base..HEAD 非空)
即视为有 diff 可发;_commit_publish_implementation_diff 在工作区已 clean(worker 已 commit)时
跳过提交返回成功,不再误报 publish_commit_failed。修 #541 类 worker-commit→no_diff→无 PR+
daemon 重复 dispatch。补 behavior test。codex 全套件 DISCOVER_STATUS:0 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #437: .refactor-loop 历史生成物与陈旧 worktree 的有界清理机制 (#548)

* #437: 新增 canonical RuntimeRetention owner,log-retention 降为一版 alias;清理覆盖 generated files+pending-events compaction+stale worktree;CLAUDE.md 加 #437 narrow carveout

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* hotfix: CONFLICTING managed review PR 的 stale-base 冲突自主 resolve

接线既有但孤儿的 prompts/rebase-resolve.md 进 headless 路径:managed review PR
mergeable=CONFLICTING(base 落后)时,controller 在 PR worktree 起 git merge
--no-commit --no-ff origin/<integration>——干净则直接 commit+push,有冲突则派
rebase-resolve codex(隔离 worktree 内解+stage,禁 commit/push),收到
REBASE_RESOLVE_DONE 后 controller commit + safe_push 仅推 PR head。结果再过 CI+
review-gate 把关。新增 dispatch_pr_rebase_resolve / commit_push_resolved_pr_rebase
(controller_actions)+ wakeup_plan 投影 + wakeup_runner 应用。

安全:只动 refactor/iter<N>-* PR 分支,显式 guard 拒碰 integration/review_base,
diff-filter=U 验未解冲突才 commit,任何 abort 路径 git merge --abort 留干净 worktree,
幂等(已含 base / 解析在飞则 NOOP)。修 stale-base churn 致 loop 永久停滞(一个 PR
合了其它全 CONFLICTING 无人解)的根因。codex 全套件 1589 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: rebase_resolve_actions 投影前 enrich live mergeability(修生产 gap)

自主-resolve 投影读 item.mergeable 前未 enrich,但生产 GhItem 来自 snapshot
mergeable 为空 → 永远 skip → CONFLICTING PR 不投影 dispatch_pr_rebase_resolve →
loop 仍停滞。复用同文件 _with_live_mergeability(review_evidence_redispatch_actions
已用同模式)。补 mergeable-为空-需-live-fetch 的回归测试(原测试 mock 了 mergeable
未覆盖此生产路径)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: dispatch_pr_rebase_resolve kind 进 EXECUTABLE_ACTION_KINDS(end-to-end 可执行)

_close_projection_action 的 else 分支默认 status_only=True;rebase action 的 kind
stale-base-conflicting-pr 不在 EXECUTABLE_ACTION_KINDS → 永远 status_only,runner 不
apply,CONFLICTING PR 永不自主 resolve。加该 kind(+ commit_push completion kind 如需)
进集合;controller_action 已在 RUNNER_NAMED_HELPER_ACTIONS 故随即保持 executable。补
端到端 wakeup-plan pipeline 测试(原测试只测 rebase_resolve_actions 单函数,漏了 closed-
action-projection 的 status_only 关卡)。codex 全套件 1593 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: rebase-resolve commit/dispatch 投影 gate 在实际 worktree merge 态(止 stale-marker 噪音)

commit_push_resolved_pr_rebase 之前只凭持久 REBASE_RESOLVE_DONE marker 投影,worktree
已 commit+push(#549)或 abort(#550/#551)后 marker 仍在 → 每 tick fail-closed 噪音 +
反复 0-codex(zero_streak 触警)+ stale marker 挡 #550/#551 fresh resolve。现 gate:仅当
worktree 真有 merge-in-progress(MERGE_HEAD)且无 unmerged 才投 executable commit_push;
否则不投。并让 worktree clean + 仍 CONFLICTING 的 PR 重新拿 executable dispatch_pr_rebase_resolve
(stale DONE marker 不再永久压制)。补端到端测试。codex 全套件通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec  (#549)

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec

* 修复 PR #549 review r3:#502 label-purge 适配当前 label 代码(contract-tests + architect/tests reject)

fix codex round-3 applied-4:对齐 #502 遗留 label 兼容层 purge 与近期新增 label 代码,
修 contract-tests 失败 + architect/tests reject。改 labels.py + SKILL.md + test_wakeup_plan.py。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless review_gate ci_failed 死锁:reject→FIX 移到 ci/mergeability 检查前

_review_gate_decision 之前 ci_error/mergeability 检查在 reject>0→FIX 之前 → CI 红的 PR
即使 reviewer reject 也返回 WAIT_OR_REDISPATCH:ci_failed 干等,而 CI 不修不会绿 → 死锁
(#548/#549 都中,需手动派 fix 破解)。把 reject>0→FIX 移到 ci/mergeability 检查前
(仍在 reviewer-validity/head 检查之后)→ reject 时即使 CI 红也自主派 fix(fix 同解 reject+CI)。
MERGE/MERGE_WITH_COMMENTS 判定完全不变(仍需 ci-green + mergeable + reject=0 + approve>=1),
无误合并风险。补 test_wakeup_runner 端到端测试(reject+ci-red→FIX;reject=0+ci-red 仍 WAIT;
happy path MERGE 不变;stale-head+reject 仍 WAIT)。full suite 1600 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修正 review_gate 顺序:mergeability 检查移到 reject→FIX 之前(CONFLICTING 不并发 review/fix)

上一修复(a125d19)把 reject→FIX 移到 ci+mergeability 前,破了 ci_failed 死锁但也让
CONFLICTING+reject 的 PR 路由到 FIX → 与独立的 dispatch_pr_rebase_resolve 并发跑同一
worktree(#550 出现 98-file mid-merge + reviewer 并发)。把 mergeability_error 检查移到
reject→FIX 之前:CONFLICTING→WAIT(先 rebase-resolve,不并发 review/fix);MERGEABLE+
CI红+reject→FIX(死锁修复保留);ci_error 仍在 reject→FIX 后(纯 CI 红无 reject 才 WAIT)。
MERGE 判定不变。test_wakeup_runner 90 OK(+conflicting 用例)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es (#550)

* 实现 issue #498

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es

* PR #550 review-fix output

* 新增 patrol-inspector 巡检 issue intake (#551)

* 实现 issue #541

* PR #551 review-fix output

* PR #551 review-fix output

* 修复 PR #551 contract-tests:对齐 patrol 第8 daemon + safe_push/sync_dev 测试 host.env

#551 patrol 新增 patrol_inspector_daemon(第8 daemon)→ test_anti_stop_restart 期望 7→8;
test_controller_lib_safe_push / test_sync_dev 补 CONSENSUS_RND_HOST_ENV host.env 设置
(代码按 host-config contract 需 host.env locator,rebase-resolve 丢了 base 新测试版本)。
断言未削弱(daemon 数断言强化为8)。full discovery 1634 OK + sshx 13 OK。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 PR #551 contract-tests(clean-env):e2e fixture 设 META_ESCALATION_STUCK_HOURS 隔离 de-dup 测试

test_batch_and_per_task_lock_do_not_duplicate_spawn 在 clean env(CI)下失败:#506 meta-
escalation 因 fixture mock 态被判 stuck 而 fire,产出 repository-stalled RunnerResult 污染
de-dup 断言(expected [] got [RunnerResult])。fixture host.env+env 设 META_ESCALATION_STUCK_
HOURS=999999 禁该测试的 meta-escalation,聚焦 de-dup 行为。断言未削弱。clean discovery 全过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 publish-gap:implement readiness 用 git status --porcelain 判 staged diff

原 classify_implement_attempt / wakeup_runner publish 前用 git diff --quiet 只检测 unstaged
改动;worker 正确 git add -A 后 staged diff 被误判 empty_scoped_diff,导致完成的 implement
(如 #553 干净 EXIT=0 + 885 行真实 staged diff + 有效 title/body artifacts)永远出不了 PR,
wakeup_runner 对 children 反复空转 re-dispatch。改为先 git status --porcelain 判 staged/
unstaged/untracked 任一即 publish-ready,只有真干净才 fallback git diff。publish-time 建 PR
路径不变(不重蹈 #507 early-PR 空 commit/placeholder 死锁)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #552

* PR #558 remote-ci-fix output

* 移除 #552 越界加的孤立 flaky phase9-router 测试

fb2f461(#552 实现)给未改动的 phase9 router 加了 test_phase9_router_tick_summary_is_
router_local_diagnostic,与 #552「收窄 restart daemon 权威」scope 无关,且该测试 call
self.router.tick() 不 mock managed-work-snapshot fetch → CI 无 GitHub 时 fetch-failed
诊断行污染输出致 anchored regex 不匹配(flaky),挡 CI。main 从无此测试。按删除优先+scope
收口移除;若 router 诊断测试有价值应在 phase9-focused PR 以 hermetic 形式正式加。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
loning added a commit that referenced this pull request Jun 6, 2026
* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。



* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。



* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。



* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。



* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。



* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions 309 通过。



* hotfix r12: run_once 不再让 spawn-batch starve drain-only lifecycle — ready PR headless merge,backlog 能 drain

根因(已核实):wakeup_plan 每 tick 把 SPAWN actions(implement intent + design-consensus #495/#496/#490/#491/#418,index 0-5)排在 lifecycle review_gate(#480/#473/#402,index 6-8)之前;run_once 旧逻辑 `if applied_spawns>0 and not is_spawn_action: break` → 只要派了任一 spawn,首个 lifecycle 即 break 整 tick。design-consensus 几乎总有 spawn 活 → review_gate/merge 永远 starve → #473(approve/approve/comment → MERGE_WITH_COMMENTS,MERGEABLE+CI 绿)永不 merge,active 数永不下降。

修法(最小,核心 dispatch loop):
- 引入 consumes_spawn_budget = is_spawn_action or _uses_spawn_budget(action);超 budget 时 `continue`(不 break)以便仍能抵达后续 drain-only lifecycle。
- _uses_spawn_budget:dispatch_reviewers=True、review_gate 仅当决策为 FIX(会派 fix worker)=True;否则 review_gate(MERGE/MERGE_WITH_COMMENTS)、close 等 drain-only=False → 不占 spawn budget、floor 填满后仍被评估执行。
- 保留 r6 的 spawn launch-failure break/retry 与 dispatch_design_consensus no-intents skip-and-continue;真值表/head-binding/CI-green/mergeable 安全语义不变。

结果:每 tick 既用 spawn 填满 floor,又评估 merge/close 等 drain-only lifecycle,backlog 能 drain。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions+pr_checks 309 通过;新增 test_wakeup_runner_lifecycle_review_gate_not_starved_after_spawn_batch。



* hotfix r13: 修 WakeupRunner._run_command 把 --repo 注入到 gh 子命令前致全部 gh 调用 malformed — review→merge 根因

根因(实测确认):_run_command 对所有 gh 命令在 full[1:1] 插 --repo(子命令之前)。gh 不接受 --repo 作 pre-subcommand 全局 flag,且 gh api 根本不吃 --repo(repo 在 URL):`gh --repo O/R api repos/O/R/pulls/473` → rc=1 "unknown flag: --repo"。于是 wakeup-runner 的每个 gh 调用都 malformed:CI 读(PrChecksProjection(runner=_run_command) 的 gh api pulls/check-runs)→ ci_unavailable:pull_api_failure;mergeability(gh pr view)→ mergeability_unavailable;live-state 等同理。→ review gate 永远读不到 CI/mergeable → #473(approve/approve/comment=MERGE_WITH_COMMENTS,绿)、#402#480 永不 headless 落地。r11 的 retry 只是重复同一 malformed 命令。直连 PrChecksProjection()/直连 gh 用的是 plain default runner(无注入)所以正常,掩盖了 bug。

最小修法:_run_command 仅对 `gh pr`/`gh issue` 注入 --repo,且放在子命令(及其 verb)之后的合法位置;`gh api` 完全不动;绝不 pre-subcommand 注入;已存在 --repo 则不重复。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+pr_checks+wakeup_plan+controller_actions 312 通过;新增 argv-shape 测试 + e2e(stub subprocess.run 拒绝 malformed `gh --repo ... api`,ready PR 仍 merge)。



* hotfix r14: managed draft PR ready-then-merge — review gate 不再硬挡 pr_draft

根因(r13 修好 gh 调用后浮现):review_gate 的 _review_gate_mergeability_error 把 isDraft=True 当 WAIT_OR_REDISPATCH:pr_draft 硬挡。但本 loop draft-until-consensus:PR 开为 draft 直到 review 共识,merge_pr 在决策 MERGE/MERGE_WITH_COMMENTS 时 ready-then-merge。于是绿 gate 的 managed draft(如 #473 approve/approve/comment)永远卡 pr_draft、永不 headless 落地。

最小修法:
- wakeup_runner:删除 mergeability 检查里的 isDraft→pr_draft 硬挡(仍挡 mergeable!=MERGEABLE,即 CONFLICTING/DIRTY)。
- controller_actions.merge_pr:对 live draft PR 先校验 crnd:lifecycle:managed 再 gh pr ready(非 managed draft 不 ready,写 CONTROLLER_ACTION_BLOCKED:target-not-managed 并返回 2);保留既有 ready-then-merge。
- 真值表/head-binding/CI-green/conflicting-blocks 安全语义不变;readying 仅限 managed PR。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan+pr_checks 316 通过;新增 managed-draft merge + 真实 plan→runner→controller ready-then-merge e2e + conflicting/非managed 安全用例。



* #409: 移除 .refactor-loop/host.env runtime fallback,CONSENSUS_RND_HOST_ENV 为唯一 host fact locator(缺失 fail-closed);迁移依赖 legacy fallback 的 test fixture (#473)

* hotfix r15 (sshx 共识 B 之一): 统一 gh argv 构造到单一 build_gh_argv helper — 防 r13 类 --repo bug 复发

sshx 一致共识 B 的硬化第1步:把分散重复的 gh --repo 处理收口到 codex_refactor_loop/gh_invoke.py 的 build_gh_argv(slug, argv):gh api 永不加 --repo(repo 在 URL);gh pr/issue 仅在 subcommand 之后、缺失时加 --repo <slug>;绝不 pre-subcommand。wakeup_runner._run_command / ControllerActions.gh / PrChecksProjection 三处 API 调用全部改走该 helper,删除各自的内联 --repo 启发式。行为保持不变(含 r13 修复)。

验证:characterization + source-regression 锁在 test_gh_invoke.py(9 测试);controller 独立重跑 test_gh_invoke+pr_checks+wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan 326 通过;pr_checks 直跑 --help 兼容。

注:这是硬化(防复发),不直接提升并发;并发瓶颈在上游 implement→publish 阶段,接下来单独处理。



* hotfix r16 (sshx 共识): 打通 implement→publish 解锁并发瓶颈 — markerless/stale implement 重派 + 安全门控发布

sshx codex-cli triplet 共识(minimal/structural/delete + meta-judge):10 个 design-solving issue 已达成共识但卡在 implement→publish(implement 早跑过却 markerless/未提交/过期 base/没 PR;dispatch_consensus_implementation 被 local_iter_branch 抑制、publish 被 verified_pr_head_unavailable 抑制)→ 无新可派工作 → 并发 ~1。

修法(wakeup_plan/wakeup_runner/controller_actions/git.py):
- success-aware 重派:implement 分支/worktree 存在但无 valid clean IMPLEMENT_DONE:ok marker(markerless/failed)或 base 过期 → 重派;fresh_safe_worktree 把 canonical worktree reset/recreate 到当前 origin/$INTEGRATION_BRANCH;仅 genuine in-flight / 已有干净 PR / 待发布 clean marker 才抑制。
- 发布门控(严防误发 stale/wrong-scope):publish_implementation_output 仅在 canonical identity(refactor/iter<issue>-<candidate> + worktree 实际分支匹配)+ fresh integration base(merge-base==origin/integration,过期 base block)+ managed open issue + 无重复 PR + 非空 scoped diff 时,commit→push→open PR→派 reviewers;否则 block。
- wakeup_plan 用 canonical_implementation_identity/single_linked_managed_issue/clean_scoped_diff 替代 verified_pr_head 抑制。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 330 通过。

已知待修(follow-up):worker 把 PR title/body/commit 文案改成英文,违反「GitHub artifact 中文」策略,下一 commit 恢复中文。



* hotfix r17: fresh consensus-implement 重派前清除 terminal 非可发布 implement log — 让卡住的 implement 真正启动

承接 r16:r16 让 markerless/stale implement 重派(reset worktree),但旧的 EXIT=1/markerless implement log 仍占 spawn 的 target_log_absent 前置 → fresh implement 不启动(同一类「按存在抑制」,implement-spawn-log 层)。

修法(controller_actions,success-aware):fresh consensus-implementation dispatch 写 spawn intent 前,仅清除 terminal 非可发布 implement log(EXIT!=0 失败 / EXIT=0 无 IMPLEMENT_DONE:ok marker);保留 genuinely in-flight(无 EXIT)与 clean publish-ready(EXIT=0 + 干净 marker)log 不动。于是卡住的 markerless/failed implement 重派后能真正 launch、跑在 fresh base、产出干净 marker → r16 门控发布。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 333 通过。

设计说明:并发瓶颈用确定性逻辑修对(ready=clean EXIT=0+marker;parallel=scope_paths 不相交),不引入 LLM-in-loop 分发判断(daemon-first;sshx codex 三人组一致 revise:LLM 最多 shadow-mode,不入决策回路)。



* hotfix r18: implement-lifecycle 收敛为单一 success-aware 谓词 + runner 路径自清陈旧 log — headless 自愈,不再需手动清 log

承接 r16/r17(r17 把清 log 放进被抑制的 dispatch 路径,从没执行)。新增 implement_lifecycle.py 单一事实源 classify_implement_attempt → in_flight | publish_ready | redispatch,plan/runner/controller 共用:
- runner spawn-apply 路径 _spawn_log_suppresses_retry 仅在 in_flight|publish_ready 时抑制;redispatch(EXIT!=0/markerless/stale-base) 不抑制且 _clear_redispatchable_spawn_log 在 spawn 实际应用处清掉陈旧终态 log → fresh implement 真启动(修 r17 misplacement,免手动清)。
- publish 仅 publish_ready(clean IMPLEMENT_DONE:ok + canonical identity + fresh base + 非空 scoped diff);clean-marker 但 stale-base 改 redispatch 而非死锁(#421 edge)。
- 确定性逻辑(非 LLM-in-loop;daemon-first);merge-gate/#191/#322/#396 安全语义不变。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 339 通过。



* 修复 phase9-router triplet-evidence-invalid 误判致 headless design-consensus wedge

solver prompt 注入的 issue source snapshot 含上一轮 design-consensus 的
audit-trail(peer solver log 路径)时,_peer_solver_reference_violation
扫描整个 prompt 误判为 peer-isolation 违规,fail-closed 拒派 meta-judge,
使所有 body 含历史 consensus 记录的 issue 永久 wedge。

修复:peer-isolation 扫描只覆盖 router-controlled 区域,剥离
'## Issue source snapshot' 到 '## Full solver template' 之间的 issue
作者内容;router header / solver template 注入的真实 peer 引用仍拦截。
加两个 behavior test 覆盖 snapshot-排除 与 router-区域-仍拦截。

dogfood headless 实测:reload 后 418/437/474/490/491/493/494/495 全部
恢复 solver→judge→consensus 自驱,#494 已自驱到 implement。



* CLAUDE.md: 加 consensus-rnd:foundational-invariants sentinel block

dogfood bootstrap 的 check-project-rules probe 要求 PROJECT_RULES 含此
fixed-point block;缺失时 probe fail-closed 阻断 headless restart。内容
为 probe 生成的 canonical FI-001~007,镜像既有设计哲学,不引入新约束。



* 修复 markerless implement 致 publish 卡死的 headless gap

implement worker 干净退出(EXIT=0)但把 IMPLEMENT_DONE marker 只写进 run
artifact(runs/implement-issue-<id>.md)而非 log 末尾时(codex stdout marker
落点不可靠),completed_marker_actions 只扫 log marker → markerless → 不生成
publish action → design→implement→PR 链卡在 implement 后。实测 #421:EXIT=0
+ artifact 有 IMPLEMENT_DONE:issue-421:ok + 9 文件 staged,却无 PR、label 仍
停在 design-solving。

修复:对 clean-exit 的 implement-issue log,log markerless 时 fallback 读取
run artifact 末尾的 IMPLEMENT_DONE marker,复用 review verdict 已有的
artifact-first 模式。窄作用域(仅 implement-issue + clean-exit),配 2 个
behavior test;全套 wakeup_plan 138 tests green。



* 补全 markerless implement publish:revalidation 也读 run artifact marker

8aeea89 修了 wakeup_plan detection 端,但 wakeup-runner 的 source-marker
revalidation(_source_log_has_clean_marker)仍只扫 log,markerless implement
publish 仍被 reject(clean_exit_marker_missing)。补全:revalidation 对
clean-exit implement-issue log 在 log markerless 时 fallback 读
runs/implement-issue-<id>.md 的 marker,与 detection 端一致;配 behavior test,
全套 wakeup_runner 76 tests green。

注:dogfood 实测确认 markerless 是系统性病根(还影响 readiness 重派、review
verdict 等多处),应走系统性统一(见 #491 日志/observability 与后续 marker-reading
收口);本 commit 只补 implement publish 这条链。



* 日志详细化:wakeup-runner tick 显示全状态计数 + 被掩盖的 blocked/skipped 详情

旧 _wakeup_tick_action 只看 results[0],一个 tick 处理多 action 时 blocked(如
publish 失败)被成功的 spawn 掩盖、完全不可见;graphql-backoff 固定显示误导的
'remaining=unknown'。dogfood 调试时这逼得每次翻 ledger 才知道真实发生了什么。

改:tick log 显示 [applied=N,blocked=M,...] 全状态计数 + 被掩盖的 blocked/skipped
具体 reason+action(graphql-backoff 作整-tick 门控单独报、去掉 unknown);dispatched
headline 保留。更新 test 反映可见性提升,全套 wakeup_runner 76 tests green。



* 补全 markerless implement 第三环:readiness 谓词读 run artifact marker

classify_implement_attempt(r18 单一 success-aware 谓词)只扫 log 找
IMPLEMENT_DONE:ok,markerless log(marker 落 artifact)→ redispatch:markerless →
readiness 不 suppress → 重派覆盖已完成工作(dogfood 实测 #421 重派 4 次、#493
IMPLEMENT_DONE:ok→重派→:partial 工作丢失)。

补全:markerless log 时 fallback 读 runs/implement-<cluster>.md 的
IMPLEMENT_DONE:ok,与 detection(8aeea89)/revalidation(dfacc64)一致。窄作用域 +
r17/r18 兼容:只接受 :ok,partial/失败/真 markerless(无 artifact)仍 redispatch
recovery — 现有 markerless-redispatch test(wakeup_plan/wakeup_runner/
controller_actions 共 304 tests)全绿,新增 2 behavior test。

至此 implement→PR 的 markerless 三环(detection/revalidation/readiness)打通;
review 链 markerless 与系统性统一抽象交 #499 共识。



* #500: design-consensus 编排重设计 — phase9-router 唯一派发 owner,删 wakeup-runner 双重派发

落地 #500 r4 consensus(structural framing,no-new-schema):
- phase9-router 成为唯一 design-consensus worker intent owner,新增
  META_RESOLVED:re-design → marker.round+1 三路 solver route
- 删除 wakeup-runner 的 dispatch_design_consensus(消除双重派发 helper_exit:3)
- wakeup-runner 只保留 closed action apply(drop→close、consensus→implement)
- dispatch_consensus_implementation readiness 后转 crnd:phase:implementing
- 无新增 schema(复用 HARNESS_SPAWN_INTENT)

修复 headless P0:reflector META_RESOLVED 无 consumer + phase9-router/wakeup-runner
双重派发致 0-codex 死锁。14 文件 +207/-282;verification 471 tests 全绿。

共识由 controller 手动驱动 design-consensus r1→r4 达成(daemon 停止期间)。



* #501 fix r1: 补 dispatch_consensus_implementation label-transition failure-branch test

tests reviewer reject:新增 label transition(gh issue edit→implementing)只测 success
path,缺 gh issue edit 返回 nonzero 时 dispatch stop before worktree/render/intent 的
failure-branch test。本 fix 补该测试。



* 修复 headless 死锁:label 移除集只留 canonical crnd:*,删除历史 alias

gh issue/pr edit --remove-label 会因仓库不存在的 label 整条 rc=1 失败。
ISSUE_LABELS_REMOVE/PR_LABELS_REMOVE 含 cleanup_aliases(emoji/legacy 名),
仓库未维护这些历史 label,导致 _move_issue_to_implementing_phase 永久失败,
consensus→implement 派发卡死、wakeup_runner 0 codex 自驱死锁。

按 maintainer 指令删除历史 label 兼容(不再管历史标签):移除集只列
canonical crnd:* phase/human/stuck label。新增 source-regression 锁定
两集 canonical-only、无 alias。



* 修复 #500 回归:phase9-router 生产 ctx 丢失 GH_REPO_SLUG 致 design-consensus intake 全死

#500(e733b1a)把 Phase9Router.__init__ 的 ctx 构造从
`LoopContext.load(repo_root=repo_root)` 改成
`LoopContext.load(repo_root=repo_root, env={"REPO_ROOT": str(repo_root)})`。
受限 env 不读 os.environ,使 daemon(经 source host.env 启动)的 ctx
gh_repo_slug=None → `_open_design_consensus_issues` 第一行 fail-closed 返回 []
→ DesignConsensusIssueIntake 静默永不派 → headless 无法为任何 issue 启动
design-consensus;`_require_open_source_issue` 也因无 slug 失败(marker route
如 #490 redesign 卡在 phase9-source-state-unavailable)。

修复:revert 为 `LoopContext.load(repo_root=repo_root)`,读进程环境解析 host facts。
测试一律用 `Phase9Router(ctx=...)` 显式 ctx,不依赖受限 env;新增回归测试锁定
生产 repo_root 构造路径解析 GH_REPO_SLUG。



* 加 STALE_REVIVAL_HOURS:>阈值未推进的 stuck implement 自动 re-trigger(env 可配,默认 3h)

headless 下 partial/failed/markerless 的 implement log 会让已排队的
dispatch-consensus-implementation spawn intent 永久卡在 runner 的
target_log_absent 前置(清 log 的 dispatch_consensus_implementation 又被
pending_implement_intent 抑制)→ stuck implement 不会自愈(如 #421/494/493/474/498
的 10h partial-wedge)。

新增 host-tunable STALE_REVIVAL_HOURS(默认 3,非正/非法回落 3h)。wakeup_plan
投影 implement spawn intent 时,若目标 implement log 是 redispatchable
(partial/failed/markerless/stale-base)且 mtime 已超阈值,清掉它 →
target_log_absent 通过 → implement 自动重派。安全闸:in-flight(无终止 EXIT)永不清、
publish-ready(:ok+diff)不清、age-gate 防误清刚跑完的。

env 已登记进 SKILL.md host env surface matrix + host.env.example;5 个 behavior
test + matrix↔example 对称测试覆盖。



* 扩展 stale-revival 覆盖死 codex:in_flight 无 EXIT 且 >阈值 + 不在存活清单 也 re-trigger

最常见的 headless wedge 是 codex/supervisor 中途死亡(如 daemon 被 kill 截断),
log 永远停在 in_flight(无终止 EXIT)→ classify 永判 in_flight → 永不 redispatch。
之前只清 redispatchable(partial/failed/markerless)log,漏了这半边。

现在 _revive_stale_redispatchable_implement_log 在 log mtime 超阈值时,先按
redispatchable 清;否则若 classify 为 in_flight 且 monitor 存活清单里无该 log 的
活进程,则判定为死 worker 清掉。安全性:spawn-codex 的 no-output stall 窗口远小于
默认 3h,故 >阈值仍 in_flight 的 log 必是死 supervisor;再加 monitor 存活校验
双保险,绝不杀活 codex。新增 3 个 behavior test(死 codex revive / fresh 不碰 /
活进程不碰)。



* 加手动 trigger:consensus-rnd-cli revive-implements(立即 re-trigger 卡住的 implement,不等阈值)

_revive_stale_redispatchable_implement_log 加 force 参数:跳过 stale_revival_seconds()
age gate,但 in_flight log 在 force 下必须经 monitor 存活校验证明无活进程才清(绝不杀
正在跑的 codex)。新增 force_revive_stuck_implements() 扫所有 implement-issue-*.log
强制 revive,和新 CLI 命令 revive-implements(authority delete-log)。auto 路径
force=False 不变。新增 4 个 behavior test。



* 修 env 泄漏:测试套件 import 时隔离 ambient host.env(worktree 里跑 TEST_CMD 不再假失败)

daemon spawn 的 implement worker 在 worktree 里跑完整 TEST_CMD 时,继承的相对
CONSENSUS_RND_HOST_ENV=.config/consensus-rnd/host.env 泄漏进 temp-repo
LoopContext.load(repo_root=tmp) → 解析成 tmp/.config/... 不存在 → 假
LoopContextError(实测 concurrency_monitor 48 + restart_daemons 23 + … ≈151 errors)
→ 全套永不绿 → implement 永远 :partial → 进不了 PR。

unittest discover 在 collection 阶段先 import 所有 test_*.py 再跑;新增
test_aaa_host_env_isolation.py(字母序最先)在 import 时 pop 掉 host 注入变量,
全套在任何测试 run 前即隔离。验证:full discover 设 locator 跑 → exit 0 全绿
(此前 同条件 151 errors);targeted before/after 证 48/23/1 errors → OK。
纯测试模块,不碰 production/daemon。



* 修 markerless keystone:solver/judge marker 加 companion-artifact fallback

solver/judge codex 有时 EXIT=0 但 SOLVER_DONE/META_JUDGE_DONE marker 只落 run
artifact、没在 log 末尾,导致 phase9-router 判 triplet 不完整、永不派 judge,
design-consensus 轮卡死(实测 #505 r1 structural 214 次嵌入、0 次行首)。

把已有的 implement artifact-marker fallback 扩到 solver/judge:clean-exit log
末尾无独立 marker 时,从 companion run artifact runs/<log-stem>.md 兜底读。纯
additive(log 有 marker 时行为不变)、prefix-scoped、精确 filename regex、复用
安全的独立 marker 提取(不信嵌入/echo)。不削弱共识(仍要 3 marked solver +
judge,只让 marker 来源更稳健)。phase9/router.py + wakeup_plan.py + behavior +
source-regression tests;full suite 1367 green。



* 修 publish stale-base 无恢复 + 停 :ok churn:让 implementing 能发出 draft PR

implement :ok 但 worktree base 落后 origin/$INTEGRATION_BRANCH 时,publish 原本硬
block(publish_implementation_stale_base)且永不恢复;stale-revival 又把 stale-base
的 :ok implement 当 redispatchable 反复重派同一 stale worktree → 无限 churn 占满
floor、长时间零正式 PR(implement→首个 PR 永远开不出)。

改为:publish 前在 worktree merge origin/$INTEGRATION_BRANCH 恢复 base(冲突则
merge --abort + 明确 reason 交既有 resolver/re-dispatch);clean `:ok` 不再被
stale-revival churn(终态成功走 publish-with-recovery,不重跑);无 open PR 的 :ok
创建 draft PR(per #300 共识前 draft)+ Closes #N。controller 仍拥有 git topology,
worker 不 commit/push,不绕 review-gate/merge 真值表。controller_actions.py +
wakeup_plan.py + wakeup_runner.py + behavior/source-regression tests;full suite
1374 green。



* 修 markerless implement:EXIT=0+真diff 无干净 marker 时合成 publish 候选,止 stale-revival 空重派死循环

publish build/test 闸做安全网。



* 修 publish 顺序 bug + merge 失败派 codex 兜底 resolver:先 commit worker diff 再 merge fresh base,真冲突不 wedge 改派 resolver,幂等续跑

空判据改 git diff HEAD;顺带修 wakeup_plan stale-suppression 同类 git diff 问题。



* 实现 issue #504 (#519)

* 修 headless review-fix prompt 渲染不全:绑定全部 placeholder(PR_NUMBER/标题/轮次/分支/REVIEW_*_PATH 等),解锁 reject PR 的 fix→merge

之前 headless _dispatch_review_fix 只绑 FIX_OUTPUT_PATH,其余 ${} 未解析致 fix codex 读不到 reject 证据。



* 实现 issue #496 (#520)

* 修 review-fix codex 派到 main 的 cd bug:改在 PR worktree 跑,worktree 缺失 fail-closed

之前 _dispatch_review_fix cd=repo_root → fix 改 main(污染 daemon checkout)且不落 PR 分支(reject PR 永不 merge)。



* 实现 issue #508 (#523)

* 修 wakeup-plan action 排序:review_gate/publish 排到新工作 spawn 前,解 spawn-budget 饿死→reject PR 可被 fix→merge



* CLAUDE.md 加宪法工程规则:异常必抛出+记可诊断日志严禁吞掉/静默;测试必断言真实行为禁无意义测试(maintainer 指令)



* 实现 issue #503 (#521)

* 增加通用工程基本规则,明确面向对象设计要求及实现细则

* 实现 issue #514 (#524)

* 完善通用面向对象设计准则,增加核心原则与实现层细则

* 实现 issue #494 (#526)

* 实现 issue #517 (#528)

* 实现 issue #505 (#510)

* 实现 issue #505

* #510 fix r1:补 phase9-router 行为测试覆盖(应对 tests reviewer reject)



---------



* 修复 headless FIX_DONE 不提交 fix 输出 gap:wakeup-runner 在 FIX_DONE re-review 前先 commit+push fix worktree

headless 下 fix codex 产出 FIX_DONE 但 worker 从不 commit,FIX_DONE 直接路由 dispatch_reviewers,
fix 输出永远留在 worktree 未提交,reviewers 永远审旧 head,reject 不收敛,阻断所有需 fix 轮的 PR
review→merge。镜像 interactive controller:FIX_DONE 源的 dispatch_reviewers 前,若 fix worktree
dirty 则 git add+commit+safe_push,clean 则 no-op。附 2 个 behavior test(dirty 提交/clean 跳过)。



* 实现 issue #491 (#531)

* 实现 issue #490 (#529)

* 实现 issue #490

* 实现 issue #490

* PR #529 review-fix output

* 实现 issue #499 (#512)

* 实现 issue #499

* PR #512 review-fix output

* 实现 issue #474 (#532)

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* PR #532 review-fix output

* 实现 issue #476 (#518)

* 实现 issue #476

* PR #518 review-fix output

* 实现 issue #509 (#527)

* 实现 issue #509

* 实现 issue #509

* spawn-claim recycle 改用 artifact-aware terminal marker:companion log 被 24h retention 删除后,已完成任务的 claim 仍可回收(读 runs/ artifact),不再永久阻断重派;running 任务无终止 marker 仍不回收(防 double-spawn)

* 实现 issue #421:发行前 clean-room 集成测试制度 (#534)

* 实现 issue #421

* rebase #421 onto fresh integration:解决 test_cli_command_router 冲突 + 校验

* 实现 issue #493:测试纪律修宪(behavior-first) (#535)

* 实现 issue #493

* rebase #493 onto fresh integration:解决冲突 + 校验

* PR #535 review-fix r1:addressed tests+quality reject(behavior-first test 调整)

* 实现 issue #506 (#536)

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* PR #536 review-fix output

* churn 根治:wakeup-plan 给 consensus-impl spawn-intent 套 open_closing_pr/terminal/in-flight 抑制(对齐 dispatch_consensus_implementation),已有 PR 的 issue 不再被重派 implement

* 实现 issue #507 (#525)

* 实现 issue #507

* 实现 issue #507

* PR #525 review-fix output

* 实现 issue #516 (#530)

* 实现 issue #516

* 实现 issue #516

* #530 fix r1:补 ManagedWorkSnapshot fetch-failure stale-cache fallback 行为测试(应对 tests reviewer reject)

* PR #530 review-fix output

* PR #530 review-fix r2:typed ManagedWorkItem projection(addresses architect 类型边界 reject + tests + contract-tests)

* PR #530 review-fix r3:anchor ManagedWorkSnapshot read surface in authorization mirror + cross-artifact source-regression(addresses architect governance reject)

* PR #530 review-fix r4:add canonical+legacy managed-label discovery regression test(addresses tests reject)

* 修复 worker marker reader 误判相同重复 marker 为冲突

codex 常把终止 marker 回显 2-3 次(含 diff + 前缀行),导致
read_worker_terminal_marker 返回 duplicate_or_conflicting,review 真值表
永不收敛、所有 headless review→merge 卡死。改为:相同重复 marker 折叠为
有效,仅当存在 2+ 个不同 marker 值才判 duplicate_or_conflicting。
覆盖 _last_final_marker / _sentinel_adjacent_marker /
_marker_from_companion_artifact,保留 malformed 与 foreign-prefix 检测。



* Reserve implementation PR for issue #537 (#540)

⟦AI:AUTO-LOOP⟧

* 实现 issue #511 (#522)

* 实现 issue #511

* PR #522 review-fix output

* PR #522 review-fix output

* 移除误入 PR 的 .refactor-loop 运行 artifact(architect r8 reject)

resolve-pr522-merge.md 是一次性合并解决 summary,属生成物,不应进 durable diff
(CLAUDE.md「生成物不当事实源」)。解决说明保留在 commit message / PR body。



---------



* 修复早期 PR reservation 崩溃(#511 回归,阻断所有 implement 派发)

_reserve_implementation_pr 用 worker 富正文路径开 reservation PR,但该文件在
reservation 时尚不存在 → FileNotFoundError(未被 except RuntimeError 捕获)→
wakeup-runner tick 崩溃 → 任何 consensus issue 无法 implement → loop P0 wedge。
修复:reservation 前若 body 缺失则写占位正文(## issue #N 实现 + Closes + sentinel,
publish 会拒占位逼 worker 产真正文);reservation 幂等(已有 open PR 直接返回;
已有 remote head 则 reset 到 integration + force-with-lease push);捕获 OSError。



* Reserve implementation PR for issue #543 (#544)

⟦AI:AUTO-LOOP⟧

* Reserve implementation PR for issue #541 (#546)

⟦AI:AUTO-LOOP⟧

* revert early-PR reservation(#507):不再开空占位 PR,publish 出真内容才开 PR

dispatch_consensus_implementation 不再 reserve/开 PR;publish_implementation_output
恢复 pre-#507 行为——implement 出非空 diff 才 commit+push+open_pr_with_label(用 worker
真 title/body,验证非占位);空 diff 不开 PR、不 merge、不关 issue。删除占位机制
(_reserve_implementation_pr / _placeholder_*),改 wakeup_plan/runner 的 early_pr_missing 投影。
根因:空占位 PR 被 reviewer 在 implement publish 前空合,假性关闭 #537/#541/#543。
全量套件 1496 passed。



* 实现 issue #542:删除 redispatch payload 冗余 head_sha (#547)

移除 review redispatch 的重复 head_sha payload

* hotfix: stale consensus-implement intent 指向已删 worktree 不再 suppress fresh re-dispatch

consensus_implementation_suppressed_reason 的 pending_implement_intent 分支增加 worktree 存在性
守卫(接入既有 _canonical_consensus_worktree_exists):仅当 stale pending intent 的 canonical
worktree 仍存在时才 suppress。revert early-PR reservation(#507)后,#537/#541/#543 的 pending
implement intent 指向已删除 worktree,旧逻辑 suppress fresh re-dispatch,而 wakeup-runner 不断把
stale intent spawn 进死 cd 致 os error 2 / EXIT=1 死循环,阻断 consensus→implement 自主链路。
现 worktree 缺失即放行 fresh dispatch 重建 worktree。

补 test_wakeup_plan(worktree 缺失不 suppress / worktree 存在仍 suppress)+ 更新
test_controller_actions 锁旧行为的 subTest(pending case 建 canonical worktree 以保留
reject-before-fresh_safe_worktree 意图)。全套件 1557 passed。



* hotfix: spawn-claim lock 持有者 pid 已死即可回收(自愈,防 cleared-log 永久 HELD)

_existing_claim_is_recyclable 增加 pid-liveness 回退:当 lock 记录的持有者 pid 已死(os.kill
pid 0 抛 ProcessLookupError)时即可回收,保留既有 terminal-marker 回收与 live-spawn 保护
(pid 存活+无 marker 仍不回收)+ metadata-mismatch fail-closed。根因:implement 失败(EXIT=1)
留 stale lock,dispatch_consensus_implementation 重派时清掉 log → #490 spawn-claim 只在 log 有
EXIT= 时回收 → cleared log 无 marker → 死进程 lock 无法回收 → SPAWN_CLAIM_HELD 永久死锁,
阻断 consensus→implement 重派(#537/#541/#543)。补 7 个 behavior test。全套件 1560 passed。



* hotfix: publish_implementation_output 接受 worker 已 commit 的实现 diff

_require_publish_implementation_diff 之前只看 git diff HEAD --quiet(未提交改动),
worker 一旦自己 commit(在自己分支上,隔离无害)工作区就 clean → 误判 no_diff → 不开 PR。
现改为:有未提交改动 OR HEAD 相对 integration base 有 committed delta(merge-base..HEAD 非空)
即视为有 diff 可发;_commit_publish_implementation_diff 在工作区已 clean(worker 已 commit)时
跳过提交返回成功,不再误报 publish_commit_failed。修 #541 类 worker-commit→no_diff→无 PR+
daemon 重复 dispatch。补 behavior test。codex 全套件 DISCOVER_STATUS:0 通过。



* 实现 issue #437: .refactor-loop 历史生成物与陈旧 worktree 的有界清理机制 (#548)

* #437: 新增 canonical RuntimeRetention owner,log-retention 降为一版 alias;清理覆盖 generated files+pending-events compaction+stale worktree;CLAUDE.md 加 #437 narrow carveout

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* hotfix: CONFLICTING managed review PR 的 stale-base 冲突自主 resolve

接线既有但孤儿的 prompts/rebase-resolve.md 进 headless 路径:managed review PR
mergeable=CONFLICTING(base 落后)时,controller 在 PR worktree 起 git merge
--no-commit --no-ff origin/<integration>——干净则直接 commit+push,有冲突则派
rebase-resolve codex(隔离 worktree 内解+stage,禁 commit/push),收到
REBASE_RESOLVE_DONE 后 controller commit + safe_push 仅推 PR head。结果再过 CI+
review-gate 把关。新增 dispatch_pr_rebase_resolve / commit_push_resolved_pr_rebase
(controller_actions)+ wakeup_plan 投影 + wakeup_runner 应用。

安全:只动 refactor/iter<N>-* PR 分支,显式 guard 拒碰 integration/review_base,
diff-filter=U 验未解冲突才 commit,任何 abort 路径 git merge --abort 留干净 worktree,
幂等(已含 base / 解析在飞则 NOOP)。修 stale-base churn 致 loop 永久停滞(一个 PR
合了其它全 CONFLICTING 无人解)的根因。codex 全套件 1589 passed。



* hotfix: rebase_resolve_actions 投影前 enrich live mergeability(修生产 gap)

自主-resolve 投影读 item.mergeable 前未 enrich,但生产 GhItem 来自 snapshot
mergeable 为空 → 永远 skip → CONFLICTING PR 不投影 dispatch_pr_rebase_resolve →
loop 仍停滞。复用同文件 _with_live_mergeability(review_evidence_redispatch_actions
已用同模式)。补 mergeable-为空-需-live-fetch 的回归测试(原测试 mock 了 mergeable
未覆盖此生产路径)。



* hotfix: dispatch_pr_rebase_resolve kind 进 EXECUTABLE_ACTION_KINDS(end-to-end 可执行)

_close_projection_action 的 else 分支默认 status_only=True;rebase action 的 kind
stale-base-conflicting-pr 不在 EXECUTABLE_ACTION_KINDS → 永远 status_only,runner 不
apply,CONFLICTING PR 永不自主 resolve。加该 kind(+ commit_push completion kind 如需)
进集合;controller_action 已在 RUNNER_NAMED_HELPER_ACTIONS 故随即保持 executable。补
端到端 wakeup-plan pipeline 测试(原测试只测 rebase_resolve_actions 单函数,漏了 closed-
action-projection 的 status_only 关卡)。codex 全套件 1593 passed。



* hotfix: rebase-resolve commit/dispatch 投影 gate 在实际 worktree merge 态(止 stale-marker 噪音)

commit_push_resolved_pr_rebase 之前只凭持久 REBASE_RESOLVE_DONE marker 投影,worktree
已 commit+push(#549)或 abort(#550/#551)后 marker 仍在 → 每 tick fail-closed 噪音 +
反复 0-codex(zero_streak 触警)+ stale marker 挡 #550/#551 fresh resolve。现 gate:仅当
worktree 真有 merge-in-progress(MERGE_HEAD)且无 unmerged 才投 executable commit_push;
否则不投。并让 worktree clean + 仍 CONFLICTING 的 PR 重新拿 executable dispatch_pr_rebase_resolve
(stale DONE marker 不再永久压制)。补端到端测试。codex 全套件通过。



* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec  (#549)

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec

* 修复 PR #549 review r3:#502 label-purge 适配当前 label 代码(contract-tests + architect/tests reject)

fix codex round-3 applied-4:对齐 #502 遗留 label 兼容层 purge 与近期新增 label 代码,
修 contract-tests 失败 + architect/tests reject。改 labels.py + SKILL.md + test_wakeup_plan.py。



---------



* 修复 headless review_gate ci_failed 死锁:reject→FIX 移到 ci/mergeability 检查前

_review_gate_decision 之前 ci_error/mergeability 检查在 reject>0→FIX 之前 → CI 红的 PR
即使 reviewer reject 也返回 WAIT_OR_REDISPATCH:ci_failed 干等,而 CI 不修不会绿 → 死锁
(#548/#549 都中,需手动派 fix 破解)。把 reject>0→FIX 移到 ci/mergeability 检查前
(仍在 reviewer-validity/head 检查之后)→ reject 时即使 CI 红也自主派 fix(fix 同解 reject+CI)。
MERGE/MERGE_WITH_COMMENTS 判定完全不变(仍需 ci-green + mergeable + reject=0 + approve>=1),
无误合并风险。补 test_wakeup_runner 端到端测试(reject+ci-red→FIX;reject=0+ci-red 仍 WAIT;
happy path MERGE 不变;stale-head+reject 仍 WAIT)。full suite 1600 passed。



* 修正 review_gate 顺序:mergeability 检查移到 reject→FIX 之前(CONFLICTING 不并发 review/fix)

上一修复(a125d19)把 reject→FIX 移到 ci+mergeability 前,破了 ci_failed 死锁但也让
CONFLICTING+reject 的 PR 路由到 FIX → 与独立的 dispatch_pr_rebase_resolve 并发跑同一
worktree(#550 出现 98-file mid-merge + reviewer 并发)。把 mergeability_error 检查移到
reject→FIX 之前:CONFLICTING→WAIT(先 rebase-resolve,不并发 review/fix);MERGEABLE+
CI红+reject→FIX(死锁修复保留);ci_error 仍在 reject→FIX 后(纯 CI 红无 reject 才 WAIT)。
MERGE 判定不变。test_wakeup_runner 90 OK(+conflicting 用例)。



* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es (#550)

* 实现 issue #498

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es

* PR #550 review-fix output

* 新增 patrol-inspector 巡检 issue intake (#551)

* 实现 issue #541

* PR #551 review-fix output

* PR #551 review-fix output

* 修复 PR #551 contract-tests:对齐 patrol 第8 daemon + safe_push/sync_dev 测试 host.env

#551 patrol 新增 patrol_inspector_daemon(第8 daemon)→ test_anti_stop_restart 期望 7→8;
test_controller_lib_safe_push / test_sync_dev 补 CONSENSUS_RND_HOST_ENV host.env 设置
(代码按 host-config contract 需 host.env locator,rebase-resolve 丢了 base 新测试版本)。
断言未削弱(daemon 数断言强化为8)。full discovery 1634 OK + sshx 13 OK。



* 修复 PR #551 contract-tests(clean-env):e2e fixture 设 META_ESCALATION_STUCK_HOURS 隔离 de-dup 测试

test_batch_and_per_task_lock_do_not_duplicate_spawn 在 clean env(CI)下失败:#506 meta-
escalation 因 fixture mock 态被判 stuck 而 fire,产出 repository-stalled RunnerResult 污染
de-dup 断言(expected [] got [RunnerResult])。fixture host.env+env 设 META_ESCALATION_STUCK_
HOURS=999999 禁该测试的 meta-escalation,聚焦 de-dup 行为。断言未削弱。clean discovery 全过。



---------



* 修复 publish-gap:implement readiness 用 git status --porcelain 判 staged diff

原 classify_implement_attempt / wakeup_runner publish 前用 git diff --quiet 只检测 unstaged
改动;worker 正确 git add -A 后 staged diff 被误判 empty_scoped_diff,导致完成的 implement
(如 #553 干净 EXIT=0 + 885 行真实 staged diff + 有效 title/body artifacts)永远出不了 PR,
wakeup_runner 对 children 反复空转 re-dispatch。改为先 git status --porcelain 判 staged/
unstaged/untracked 任一即 publish-ready,只有真干净才 fallback git diff。publish-time 建 PR
路径不变(不重蹈 #507 early-PR 空 commit/placeholder 死锁)。



* 实现 issue #552

* PR #558 remote-ci-fix output

* 移除 #552 越界加的孤立 flaky phase9-router 测试

fb2f461(#552 实现)给未改动的 phase9 router 加了 test_phase9_router_tick_summary_is_
router_local_diagnostic,与 #552「收窄 restart daemon 权威」scope 无关,且该测试 call
self.router.tick() 不 mock managed-work-snapshot fetch → CI 无 GitHub 时 fetch-failed
诊断行污染输出致 anchored regex 不匹配(flaky),挡 CI。main 从无此测试。按删除优先+scope
收口移除;若 router 诊断测试有价值应在 phase9-focused PR 以 hermetic 形式正式加。



---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
loning added a commit that referenced this pull request Jun 6, 2026
* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions 309 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r12: run_once 不再让 spawn-batch starve drain-only lifecycle — ready PR headless merge,backlog 能 drain

根因(已核实):wakeup_plan 每 tick 把 SPAWN actions(implement intent + design-consensus #495/#496/#490/#491/#418,index 0-5)排在 lifecycle review_gate(#480/#473/#402,index 6-8)之前;run_once 旧逻辑 `if applied_spawns>0 and not is_spawn_action: break` → 只要派了任一 spawn,首个 lifecycle 即 break 整 tick。design-consensus 几乎总有 spawn 活 → review_gate/merge 永远 starve → #473(approve/approve/comment → MERGE_WITH_COMMENTS,MERGEABLE+CI 绿)永不 merge,active 数永不下降。

修法(最小,核心 dispatch loop):
- 引入 consumes_spawn_budget = is_spawn_action or _uses_spawn_budget(action);超 budget 时 `continue`(不 break)以便仍能抵达后续 drain-only lifecycle。
- _uses_spawn_budget:dispatch_reviewers=True、review_gate 仅当决策为 FIX(会派 fix worker)=True;否则 review_gate(MERGE/MERGE_WITH_COMMENTS)、close 等 drain-only=False → 不占 spawn budget、floor 填满后仍被评估执行。
- 保留 r6 的 spawn launch-failure break/retry 与 dispatch_design_consensus no-intents skip-and-continue;真值表/head-binding/CI-green/mergeable 安全语义不变。

结果:每 tick 既用 spawn 填满 floor,又评估 merge/close 等 drain-only lifecycle,backlog 能 drain。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions+pr_checks 309 通过;新增 test_wakeup_runner_lifecycle_review_gate_not_starved_after_spawn_batch。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r13: 修 WakeupRunner._run_command 把 --repo 注入到 gh 子命令前致全部 gh 调用 malformed — review→merge 根因

根因(实测确认):_run_command 对所有 gh 命令在 full[1:1] 插 --repo(子命令之前)。gh 不接受 --repo 作 pre-subcommand 全局 flag,且 gh api 根本不吃 --repo(repo 在 URL):`gh --repo O/R api repos/O/R/pulls/473` → rc=1 "unknown flag: --repo"。于是 wakeup-runner 的每个 gh 调用都 malformed:CI 读(PrChecksProjection(runner=_run_command) 的 gh api pulls/check-runs)→ ci_unavailable:pull_api_failure;mergeability(gh pr view)→ mergeability_unavailable;live-state 等同理。→ review gate 永远读不到 CI/mergeable → #473(approve/approve/comment=MERGE_WITH_COMMENTS,绿)、#402、#480 永不 headless 落地。r11 的 retry 只是重复同一 malformed 命令。直连 PrChecksProjection()/直连 gh 用的是 plain default runner(无注入)所以正常,掩盖了 bug。

最小修法:_run_command 仅对 `gh pr`/`gh issue` 注入 --repo,且放在子命令(及其 verb)之后的合法位置;`gh api` 完全不动;绝不 pre-subcommand 注入;已存在 --repo 则不重复。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+pr_checks+wakeup_plan+controller_actions 312 通过;新增 argv-shape 测试 + e2e(stub subprocess.run 拒绝 malformed `gh --repo ... api`,ready PR 仍 merge)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r14: managed draft PR ready-then-merge — review gate 不再硬挡 pr_draft

根因(r13 修好 gh 调用后浮现):review_gate 的 _review_gate_mergeability_error 把 isDraft=True 当 WAIT_OR_REDISPATCH:pr_draft 硬挡。但本 loop draft-until-consensus:PR 开为 draft 直到 review 共识,merge_pr 在决策 MERGE/MERGE_WITH_COMMENTS 时 ready-then-merge。于是绿 gate 的 managed draft(如 #473 approve/approve/comment)永远卡 pr_draft、永不 headless 落地。

最小修法:
- wakeup_runner:删除 mergeability 检查里的 isDraft→pr_draft 硬挡(仍挡 mergeable!=MERGEABLE,即 CONFLICTING/DIRTY)。
- controller_actions.merge_pr:对 live draft PR 先校验 crnd:lifecycle:managed 再 gh pr ready(非 managed draft 不 ready,写 CONTROLLER_ACTION_BLOCKED:target-not-managed 并返回 2);保留既有 ready-then-merge。
- 真值表/head-binding/CI-green/conflicting-blocks 安全语义不变;readying 仅限 managed PR。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan+pr_checks 316 通过;新增 managed-draft merge + 真实 plan→runner→controller ready-then-merge e2e + conflicting/非managed 安全用例。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #409: 移除 .refactor-loop/host.env runtime fallback,CONSENSUS_RND_HOST_ENV 为唯一 host fact locator(缺失 fail-closed);迁移依赖 legacy fallback 的 test fixture (#473)

* hotfix r15 (sshx 共识 B 之一): 统一 gh argv 构造到单一 build_gh_argv helper — 防 r13 类 --repo bug 复发

sshx 一致共识 B 的硬化第1步:把分散重复的 gh --repo 处理收口到 codex_refactor_loop/gh_invoke.py 的 build_gh_argv(slug, argv):gh api 永不加 --repo(repo 在 URL);gh pr/issue 仅在 subcommand 之后、缺失时加 --repo <slug>;绝不 pre-subcommand。wakeup_runner._run_command / ControllerActions.gh / PrChecksProjection 三处 API 调用全部改走该 helper,删除各自的内联 --repo 启发式。行为保持不变(含 r13 修复)。

验证:characterization + source-regression 锁在 test_gh_invoke.py(9 测试);controller 独立重跑 test_gh_invoke+pr_checks+wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan 326 通过;pr_checks 直跑 --help 兼容。

注:这是硬化(防复发),不直接提升并发;并发瓶颈在上游 implement→publish 阶段,接下来单独处理。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r16 (sshx 共识): 打通 implement→publish 解锁并发瓶颈 — markerless/stale implement 重派 + 安全门控发布

sshx codex-cli triplet 共识(minimal/structural/delete + meta-judge):10 个 design-solving issue 已达成共识但卡在 implement→publish(implement 早跑过却 markerless/未提交/过期 base/没 PR;dispatch_consensus_implementation 被 local_iter_branch 抑制、publish 被 verified_pr_head_unavailable 抑制)→ 无新可派工作 → 并发 ~1。

修法(wakeup_plan/wakeup_runner/controller_actions/git.py):
- success-aware 重派:implement 分支/worktree 存在但无 valid clean IMPLEMENT_DONE:ok marker(markerless/failed)或 base 过期 → 重派;fresh_safe_worktree 把 canonical worktree reset/recreate 到当前 origin/$INTEGRATION_BRANCH;仅 genuine in-flight / 已有干净 PR / 待发布 clean marker 才抑制。
- 发布门控(严防误发 stale/wrong-scope):publish_implementation_output 仅在 canonical identity(refactor/iter<issue>-<candidate> + worktree 实际分支匹配)+ fresh integration base(merge-base==origin/integration,过期 base block)+ managed open issue + 无重复 PR + 非空 scoped diff 时,commit→push→open PR→派 reviewers;否则 block。
- wakeup_plan 用 canonical_implementation_identity/single_linked_managed_issue/clean_scoped_diff 替代 verified_pr_head 抑制。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 330 通过。

已知待修(follow-up):worker 把 PR title/body/commit 文案改成英文,违反「GitHub artifact 中文」策略,下一 commit 恢复中文。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r17: fresh consensus-implement 重派前清除 terminal 非可发布 implement log — 让卡住的 implement 真正启动

承接 r16:r16 让 markerless/stale implement 重派(reset worktree),但旧的 EXIT=1/markerless implement log 仍占 spawn 的 target_log_absent 前置 → fresh implement 不启动(同一类「按存在抑制」,implement-spawn-log 层)。

修法(controller_actions,success-aware):fresh consensus-implementation dispatch 写 spawn intent 前,仅清除 terminal 非可发布 implement log(EXIT!=0 失败 / EXIT=0 无 IMPLEMENT_DONE:ok marker);保留 genuinely in-flight(无 EXIT)与 clean publish-ready(EXIT=0 + 干净 marker)log 不动。于是卡住的 markerless/failed implement 重派后能真正 launch、跑在 fresh base、产出干净 marker → r16 门控发布。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 333 通过。

设计说明:并发瓶颈用确定性逻辑修对(ready=clean EXIT=0+marker;parallel=scope_paths 不相交),不引入 LLM-in-loop 分发判断(daemon-first;sshx codex 三人组一致 revise:LLM 最多 shadow-mode,不入决策回路)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r18: implement-lifecycle 收敛为单一 success-aware 谓词 + runner 路径自清陈旧 log — headless 自愈,不再需手动清 log

承接 r16/r17(r17 把清 log 放进被抑制的 dispatch 路径,从没执行)。新增 implement_lifecycle.py 单一事实源 classify_implement_attempt → in_flight | publish_ready | redispatch,plan/runner/controller 共用:
- runner spawn-apply 路径 _spawn_log_suppresses_retry 仅在 in_flight|publish_ready 时抑制;redispatch(EXIT!=0/markerless/stale-base) 不抑制且 _clear_redispatchable_spawn_log 在 spawn 实际应用处清掉陈旧终态 log → fresh implement 真启动(修 r17 misplacement,免手动清)。
- publish 仅 publish_ready(clean IMPLEMENT_DONE:ok + canonical identity + fresh base + 非空 scoped diff);clean-marker 但 stale-base 改 redispatch 而非死锁(#421 edge)。
- 确定性逻辑(非 LLM-in-loop;daemon-first);merge-gate/#191/#322/#396 安全语义不变。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 339 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 phase9-router triplet-evidence-invalid 误判致 headless design-consensus wedge

solver prompt 注入的 issue source snapshot 含上一轮 design-consensus 的
audit-trail(peer solver log 路径)时,_peer_solver_reference_violation
扫描整个 prompt 误判为 peer-isolation 违规,fail-closed 拒派 meta-judge,
使所有 body 含历史 consensus 记录的 issue 永久 wedge。

修复:peer-isolation 扫描只覆盖 router-controlled 区域,剥离
'## Issue source snapshot' 到 '## Full solver template' 之间的 issue
作者内容;router header / solver template 注入的真实 peer 引用仍拦截。
加两个 behavior test 覆盖 snapshot-排除 与 router-区域-仍拦截。

dogfood headless 实测:reload 后 418/437/474/490/491/493/494/495 全部
恢复 solver→judge→consensus 自驱,#494 已自驱到 implement。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CLAUDE.md: 加 consensus-rnd:foundational-invariants sentinel block

dogfood bootstrap 的 check-project-rules probe 要求 PROJECT_RULES 含此
fixed-point block;缺失时 probe fail-closed 阻断 headless restart。内容
为 probe 生成的 canonical FI-001~007,镜像既有设计哲学,不引入新约束。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 markerless implement 致 publish 卡死的 headless gap

implement worker 干净退出(EXIT=0)但把 IMPLEMENT_DONE marker 只写进 run
artifact(runs/implement-issue-<id>.md)而非 log 末尾时(codex stdout marker
落点不可靠),completed_marker_actions 只扫 log marker → markerless → 不生成
publish action → design→implement→PR 链卡在 implement 后。实测 #421:EXIT=0
+ artifact 有 IMPLEMENT_DONE:issue-421:ok + 9 文件 staged,却无 PR、label 仍
停在 design-solving。

修复:对 clean-exit 的 implement-issue log,log markerless 时 fallback 读取
run artifact 末尾的 IMPLEMENT_DONE marker,复用 review verdict 已有的
artifact-first 模式。窄作用域(仅 implement-issue + clean-exit),配 2 个
behavior test;全套 wakeup_plan 138 tests green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 补全 markerless implement publish:revalidation 也读 run artifact marker

8aeea89 修了 wakeup_plan detection 端,但 wakeup-runner 的 source-marker
revalidation(_source_log_has_clean_marker)仍只扫 log,markerless implement
publish 仍被 reject(clean_exit_marker_missing)。补全:revalidation 对
clean-exit implement-issue log 在 log markerless 时 fallback 读
runs/implement-issue-<id>.md 的 marker,与 detection 端一致;配 behavior test,
全套 wakeup_runner 76 tests green。

注:dogfood 实测确认 markerless 是系统性病根(还影响 readiness 重派、review
verdict 等多处),应走系统性统一(见 #491 日志/observability 与后续 marker-reading
收口);本 commit 只补 implement publish 这条链。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 日志详细化:wakeup-runner tick 显示全状态计数 + 被掩盖的 blocked/skipped 详情

旧 _wakeup_tick_action 只看 results[0],一个 tick 处理多 action 时 blocked(如
publish 失败)被成功的 spawn 掩盖、完全不可见;graphql-backoff 固定显示误导的
'remaining=unknown'。dogfood 调试时这逼得每次翻 ledger 才知道真实发生了什么。

改:tick log 显示 [applied=N,blocked=M,...] 全状态计数 + 被掩盖的 blocked/skipped
具体 reason+action(graphql-backoff 作整-tick 门控单独报、去掉 unknown);dispatched
headline 保留。更新 test 反映可见性提升,全套 wakeup_runner 76 tests green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 补全 markerless implement 第三环:readiness 谓词读 run artifact marker

classify_implement_attempt(r18 单一 success-aware 谓词)只扫 log 找
IMPLEMENT_DONE:ok,markerless log(marker 落 artifact)→ redispatch:markerless →
readiness 不 suppress → 重派覆盖已完成工作(dogfood 实测 #421 重派 4 次、#493
IMPLEMENT_DONE:ok→重派→:partial 工作丢失)。

补全:markerless log 时 fallback 读 runs/implement-<cluster>.md 的
IMPLEMENT_DONE:ok,与 detection(8aeea89)/revalidation(dfacc64)一致。窄作用域 +
r17/r18 兼容:只接受 :ok,partial/失败/真 markerless(无 artifact)仍 redispatch
recovery — 现有 markerless-redispatch test(wakeup_plan/wakeup_runner/
controller_actions 共 304 tests)全绿,新增 2 behavior test。

至此 implement→PR 的 markerless 三环(detection/revalidation/readiness)打通;
review 链 markerless 与系统性统一抽象交 #499 共识。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #500: design-consensus 编排重设计 — phase9-router 唯一派发 owner,删 wakeup-runner 双重派发

落地 #500 r4 consensus(structural framing,no-new-schema):
- phase9-router 成为唯一 design-consensus worker intent owner,新增
  META_RESOLVED:re-design → marker.round+1 三路 solver route
- 删除 wakeup-runner 的 dispatch_design_consensus(消除双重派发 helper_exit:3)
- wakeup-runner 只保留 closed action apply(drop→close、consensus→implement)
- dispatch_consensus_implementation readiness 后转 crnd:phase:implementing
- 无新增 schema(复用 HARNESS_SPAWN_INTENT)

修复 headless P0:reflector META_RESOLVED 无 consumer + phase9-router/wakeup-runner
双重派发致 0-codex 死锁。14 文件 +207/-282;verification 471 tests 全绿。

共识由 controller 手动驱动 design-consensus r1→r4 达成(daemon 停止期间)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #501 fix r1: 补 dispatch_consensus_implementation label-transition failure-branch test

tests reviewer reject:新增 label transition(gh issue edit→implementing)只测 success
path,缺 gh issue edit 返回 nonzero 时 dispatch stop before worktree/render/intent 的
failure-branch test。本 fix 补该测试。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless 死锁:label 移除集只留 canonical crnd:*,删除历史 alias

gh issue/pr edit --remove-label 会因仓库不存在的 label 整条 rc=1 失败。
ISSUE_LABELS_REMOVE/PR_LABELS_REMOVE 含 cleanup_aliases(emoji/legacy 名),
仓库未维护这些历史 label,导致 _move_issue_to_implementing_phase 永久失败,
consensus→implement 派发卡死、wakeup_runner 0 codex 自驱死锁。

按 maintainer 指令删除历史 label 兼容(不再管历史标签):移除集只列
canonical crnd:* phase/human/stuck label。新增 source-regression 锁定
两集 canonical-only、无 alias。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 #500 回归:phase9-router 生产 ctx 丢失 GH_REPO_SLUG 致 design-consensus intake 全死

#500(e733b1a)把 Phase9Router.__init__ 的 ctx 构造从
`LoopContext.load(repo_root=repo_root)` 改成
`LoopContext.load(repo_root=repo_root, env={"REPO_ROOT": str(repo_root)})`。
受限 env 不读 os.environ,使 daemon(经 source host.env 启动)的 ctx
gh_repo_slug=None → `_open_design_consensus_issues` 第一行 fail-closed 返回 []
→ DesignConsensusIssueIntake 静默永不派 → headless 无法为任何 issue 启动
design-consensus;`_require_open_source_issue` 也因无 slug 失败(marker route
如 #490 redesign 卡在 phase9-source-state-unavailable)。

修复:revert 为 `LoopContext.load(repo_root=repo_root)`,读进程环境解析 host facts。
测试一律用 `Phase9Router(ctx=...)` 显式 ctx,不依赖受限 env;新增回归测试锁定
生产 repo_root 构造路径解析 GH_REPO_SLUG。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 加 STALE_REVIVAL_HOURS:>阈值未推进的 stuck implement 自动 re-trigger(env 可配,默认 3h)

headless 下 partial/failed/markerless 的 implement log 会让已排队的
dispatch-consensus-implementation spawn intent 永久卡在 runner 的
target_log_absent 前置(清 log 的 dispatch_consensus_implementation 又被
pending_implement_intent 抑制)→ stuck implement 不会自愈(如 #421/494/493/474/498
的 10h partial-wedge)。

新增 host-tunable STALE_REVIVAL_HOURS(默认 3,非正/非法回落 3h)。wakeup_plan
投影 implement spawn intent 时,若目标 implement log 是 redispatchable
(partial/failed/markerless/stale-base)且 mtime 已超阈值,清掉它 →
target_log_absent 通过 → implement 自动重派。安全闸:in-flight(无终止 EXIT)永不清、
publish-ready(:ok+diff)不清、age-gate 防误清刚跑完的。

env 已登记进 SKILL.md host env surface matrix + host.env.example;5 个 behavior
test + matrix↔example 对称测试覆盖。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 扩展 stale-revival 覆盖死 codex:in_flight 无 EXIT 且 >阈值 + 不在存活清单 也 re-trigger

最常见的 headless wedge 是 codex/supervisor 中途死亡(如 daemon 被 kill 截断),
log 永远停在 in_flight(无终止 EXIT)→ classify 永判 in_flight → 永不 redispatch。
之前只清 redispatchable(partial/failed/markerless)log,漏了这半边。

现在 _revive_stale_redispatchable_implement_log 在 log mtime 超阈值时,先按
redispatchable 清;否则若 classify 为 in_flight 且 monitor 存活清单里无该 log 的
活进程,则判定为死 worker 清掉。安全性:spawn-codex 的 no-output stall 窗口远小于
默认 3h,故 >阈值仍 in_flight 的 log 必是死 supervisor;再加 monitor 存活校验
双保险,绝不杀活 codex。新增 3 个 behavior test(死 codex revive / fresh 不碰 /
活进程不碰)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 加手动 trigger:consensus-rnd-cli revive-implements(立即 re-trigger 卡住的 implement,不等阈值)

_revive_stale_redispatchable_implement_log 加 force 参数:跳过 stale_revival_seconds()
age gate,但 in_flight log 在 force 下必须经 monitor 存活校验证明无活进程才清(绝不杀
正在跑的 codex)。新增 force_revive_stuck_implements() 扫所有 implement-issue-*.log
强制 revive,和新 CLI 命令 revive-implements(authority delete-log)。auto 路径
force=False 不变。新增 4 个 behavior test。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 env 泄漏:测试套件 import 时隔离 ambient host.env(worktree 里跑 TEST_CMD 不再假失败)

daemon spawn 的 implement worker 在 worktree 里跑完整 TEST_CMD 时,继承的相对
CONSENSUS_RND_HOST_ENV=.config/consensus-rnd/host.env 泄漏进 temp-repo
LoopContext.load(repo_root=tmp) → 解析成 tmp/.config/... 不存在 → 假
LoopContextError(实测 concurrency_monitor 48 + restart_daemons 23 + … ≈151 errors)
→ 全套永不绿 → implement 永远 :partial → 进不了 PR。

unittest discover 在 collection 阶段先 import 所有 test_*.py 再跑;新增
test_aaa_host_env_isolation.py(字母序最先)在 import 时 pop 掉 host 注入变量,
全套在任何测试 run 前即隔离。验证:full discover 设 locator 跑 → exit 0 全绿
(此前 同条件 151 errors);targeted before/after 证 48/23/1 errors → OK。
纯测试模块,不碰 production/daemon。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 markerless keystone:solver/judge marker 加 companion-artifact fallback

solver/judge codex 有时 EXIT=0 但 SOLVER_DONE/META_JUDGE_DONE marker 只落 run
artifact、没在 log 末尾,导致 phase9-router 判 triplet 不完整、永不派 judge,
design-consensus 轮卡死(实测 #505 r1 structural 214 次嵌入、0 次行首)。

把已有的 implement artifact-marker fallback 扩到 solver/judge:clean-exit log
末尾无独立 marker 时,从 companion run artifact runs/<log-stem>.md 兜底读。纯
additive(log 有 marker 时行为不变)、prefix-scoped、精确 filename regex、复用
安全的独立 marker 提取(不信嵌入/echo)。不削弱共识(仍要 3 marked solver +
judge,只让 marker 来源更稳健)。phase9/router.py + wakeup_plan.py + behavior +
source-regression tests;full suite 1367 green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 publish stale-base 无恢复 + 停 :ok churn:让 implementing 能发出 draft PR

implement :ok 但 worktree base 落后 origin/$INTEGRATION_BRANCH 时,publish 原本硬
block(publish_implementation_stale_base)且永不恢复;stale-revival 又把 stale-base
的 :ok implement 当 redispatchable 反复重派同一 stale worktree → 无限 churn 占满
floor、长时间零正式 PR(implement→首个 PR 永远开不出)。

改为:publish 前在 worktree merge origin/$INTEGRATION_BRANCH 恢复 base(冲突则
merge --abort + 明确 reason 交既有 resolver/re-dispatch);clean `:ok` 不再被
stale-revival churn(终态成功走 publish-with-recovery,不重跑);无 open PR 的 :ok
创建 draft PR(per #300 共识前 draft)+ Closes #N。controller 仍拥有 git topology,
worker 不 commit/push,不绕 review-gate/merge 真值表。controller_actions.py +
wakeup_plan.py + wakeup_runner.py + behavior/source-regression tests;full suite
1374 green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 markerless implement:EXIT=0+真diff 无干净 marker 时合成 publish 候选,止 stale-revival 空重派死循环

publish build/test 闸做安全网。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 publish 顺序 bug + merge 失败派 codex 兜底 resolver:先 commit worker diff 再 merge fresh base,真冲突不 wedge 改派 resolver,幂等续跑

空判据改 git diff HEAD;顺带修 wakeup_plan stale-suppression 同类 git diff 问题。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #504 (#519)

* 修 headless review-fix prompt 渲染不全:绑定全部 placeholder(PR_NUMBER/标题/轮次/分支/REVIEW_*_PATH 等),解锁 reject PR 的 fix→merge

之前 headless _dispatch_review_fix 只绑 FIX_OUTPUT_PATH,其余 ${} 未解析致 fix codex 读不到 reject 证据。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #496 (#520)

* 修 review-fix codex 派到 main 的 cd bug:改在 PR worktree 跑,worktree 缺失 fail-closed

之前 _dispatch_review_fix cd=repo_root → fix 改 main(污染 daemon checkout)且不落 PR 分支(reject PR 永不 merge)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #508 (#523)

* 修 wakeup-plan action 排序:review_gate/publish 排到新工作 spawn 前,解 spawn-budget 饿死→reject PR 可被 fix→merge

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CLAUDE.md 加宪法工程规则:异常必抛出+记可诊断日志严禁吞掉/静默;测试必断言真实行为禁无意义测试(maintainer 指令)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #503 (#521)

* 增加通用工程基本规则,明确面向对象设计要求及实现细则

* 实现 issue #514 (#524)

* 完善通用面向对象设计准则,增加核心原则与实现层细则

* 实现 issue #494 (#526)

* 实现 issue #517 (#528)

* 实现 issue #505 (#510)

* 实现 issue #505

* #510 fix r1:补 phase9-router 行为测试覆盖(应对 tests reviewer reject)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless FIX_DONE 不提交 fix 输出 gap:wakeup-runner 在 FIX_DONE re-review 前先 commit+push fix worktree

headless 下 fix codex 产出 FIX_DONE 但 worker 从不 commit,FIX_DONE 直接路由 dispatch_reviewers,
fix 输出永远留在 worktree 未提交,reviewers 永远审旧 head,reject 不收敛,阻断所有需 fix 轮的 PR
review→merge。镜像 interactive controller:FIX_DONE 源的 dispatch_reviewers 前,若 fix worktree
dirty 则 git add+commit+safe_push,clean 则 no-op。附 2 个 behavior test(dirty 提交/clean 跳过)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #491 (#531)

* 实现 issue #490 (#529)

* 实现 issue #490

* 实现 issue #490

* PR #529 review-fix output

* 实现 issue #499 (#512)

* 实现 issue #499

* PR #512 review-fix output

* 实现 issue #474 (#532)

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* PR #532 review-fix output

* 实现 issue #476 (#518)

* 实现 issue #476

* PR #518 review-fix output

* 实现 issue #509 (#527)

* 实现 issue #509

* 实现 issue #509

* spawn-claim recycle 改用 artifact-aware terminal marker:companion log 被 24h retention 删除后,已完成任务的 claim 仍可回收(读 runs/ artifact),不再永久阻断重派;running 任务无终止 marker 仍不回收(防 double-spawn)

* 实现 issue #421:发行前 clean-room 集成测试制度 (#534)

* 实现 issue #421

* rebase #421 onto fresh integration:解决 test_cli_command_router 冲突 + 校验

* 实现 issue #493:测试纪律修宪(behavior-first) (#535)

* 实现 issue #493

* rebase #493 onto fresh integration:解决冲突 + 校验

* PR #535 review-fix r1:addressed tests+quality reject(behavior-first test 调整)

* 实现 issue #506 (#536)

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* PR #536 review-fix output

* churn 根治:wakeup-plan 给 consensus-impl spawn-intent 套 open_closing_pr/terminal/in-flight 抑制(对齐 dispatch_consensus_implementation),已有 PR 的 issue 不再被重派 implement

* 实现 issue #507 (#525)

* 实现 issue #507

* 实现 issue #507

* PR #525 review-fix output

* 实现 issue #516 (#530)

* 实现 issue #516

* 实现 issue #516

* #530 fix r1:补 ManagedWorkSnapshot fetch-failure stale-cache fallback 行为测试(应对 tests reviewer reject)

* PR #530 review-fix output

* PR #530 review-fix r2:typed ManagedWorkItem projection(addresses architect 类型边界 reject + tests + contract-tests)

* PR #530 review-fix r3:anchor ManagedWorkSnapshot read surface in authorization mirror + cross-artifact source-regression(addresses architect governance reject)

* PR #530 review-fix r4:add canonical+legacy managed-label discovery regression test(addresses tests reject)

* 修复 worker marker reader 误判相同重复 marker 为冲突

codex 常把终止 marker 回显 2-3 次(含 diff + 前缀行),导致
read_worker_terminal_marker 返回 duplicate_or_conflicting,review 真值表
永不收敛、所有 headless review→merge 卡死。改为:相同重复 marker 折叠为
有效,仅当存在 2+ 个不同 marker 值才判 duplicate_or_conflicting。
覆盖 _last_final_marker / _sentinel_adjacent_marker /
_marker_from_companion_artifact,保留 malformed 与 foreign-prefix 检测。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reserve implementation PR for issue #537 (#540)

⟦AI:AUTO-LOOP⟧

* 实现 issue #511 (#522)

* 实现 issue #511

* PR #522 review-fix output

* PR #522 review-fix output

* 移除误入 PR 的 .refactor-loop 运行 artifact(architect r8 reject)

resolve-pr522-merge.md 是一次性合并解决 summary,属生成物,不应进 durable diff
(CLAUDE.md「生成物不当事实源」)。解决说明保留在 commit message / PR body。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复早期 PR reservation 崩溃(#511 回归,阻断所有 implement 派发)

_reserve_implementation_pr 用 worker 富正文路径开 reservation PR,但该文件在
reservation 时尚不存在 → FileNotFoundError(未被 except RuntimeError 捕获)→
wakeup-runner tick 崩溃 → 任何 consensus issue 无法 implement → loop P0 wedge。
修复:reservation 前若 body 缺失则写占位正文(## issue #N 实现 + Closes + sentinel,
publish 会拒占位逼 worker 产真正文);reservation 幂等(已有 open PR 直接返回;
已有 remote head 则 reset 到 integration + force-with-lease push);捕获 OSError。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reserve implementation PR for issue #543 (#544)

⟦AI:AUTO-LOOP⟧

* Reserve implementation PR for issue #541 (#546)

⟦AI:AUTO-LOOP⟧

* revert early-PR reservation(#507):不再开空占位 PR,publish 出真内容才开 PR

dispatch_consensus_implementation 不再 reserve/开 PR;publish_implementation_output
恢复 pre-#507 行为——implement 出非空 diff 才 commit+push+open_pr_with_label(用 worker
真 title/body,验证非占位);空 diff 不开 PR、不 merge、不关 issue。删除占位机制
(_reserve_implementation_pr / _placeholder_*),改 wakeup_plan/runner 的 early_pr_missing 投影。
根因:空占位 PR 被 reviewer 在 implement publish 前空合,假性关闭 #537/#541/#543。
全量套件 1496 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #542:删除 redispatch payload 冗余 head_sha (#547)

移除 review redispatch 的重复 head_sha payload

* hotfix: stale consensus-implement intent 指向已删 worktree 不再 suppress fresh re-dispatch

consensus_implementation_suppressed_reason 的 pending_implement_intent 分支增加 worktree 存在性
守卫(接入既有 _canonical_consensus_worktree_exists):仅当 stale pending intent 的 canonical
worktree 仍存在时才 suppress。revert early-PR reservation(#507)后,#537/#541/#543 的 pending
implement intent 指向已删除 worktree,旧逻辑 suppress fresh re-dispatch,而 wakeup-runner 不断把
stale intent spawn 进死 cd 致 os error 2 / EXIT=1 死循环,阻断 consensus→implement 自主链路。
现 worktree 缺失即放行 fresh dispatch 重建 worktree。

补 test_wakeup_plan(worktree 缺失不 suppress / worktree 存在仍 suppress)+ 更新
test_controller_actions 锁旧行为的 subTest(pending case 建 canonical worktree 以保留
reject-before-fresh_safe_worktree 意图)。全套件 1557 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: spawn-claim lock 持有者 pid 已死即可回收(自愈,防 cleared-log 永久 HELD)

_existing_claim_is_recyclable 增加 pid-liveness 回退:当 lock 记录的持有者 pid 已死(os.kill
pid 0 抛 ProcessLookupError)时即可回收,保留既有 terminal-marker 回收与 live-spawn 保护
(pid 存活+无 marker 仍不回收)+ metadata-mismatch fail-closed。根因:implement 失败(EXIT=1)
留 stale lock,dispatch_consensus_implementation 重派时清掉 log → #490 spawn-claim 只在 log 有
EXIT= 时回收 → cleared log 无 marker → 死进程 lock 无法回收 → SPAWN_CLAIM_HELD 永久死锁,
阻断 consensus→implement 重派(#537/#541/#543)。补 7 个 behavior test。全套件 1560 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: publish_implementation_output 接受 worker 已 commit 的实现 diff

_require_publish_implementation_diff 之前只看 git diff HEAD --quiet(未提交改动),
worker 一旦自己 commit(在自己分支上,隔离无害)工作区就 clean → 误判 no_diff → 不开 PR。
现改为:有未提交改动 OR HEAD 相对 integration base 有 committed delta(merge-base..HEAD 非空)
即视为有 diff 可发;_commit_publish_implementation_diff 在工作区已 clean(worker 已 commit)时
跳过提交返回成功,不再误报 publish_commit_failed。修 #541 类 worker-commit→no_diff→无 PR+
daemon 重复 dispatch。补 behavior test。codex 全套件 DISCOVER_STATUS:0 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #437: .refactor-loop 历史生成物与陈旧 worktree 的有界清理机制 (#548)

* #437: 新增 canonical RuntimeRetention owner,log-retention 降为一版 alias;清理覆盖 generated files+pending-events compaction+stale worktree;CLAUDE.md 加 #437 narrow carveout

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* hotfix: CONFLICTING managed review PR 的 stale-base 冲突自主 resolve

接线既有但孤儿的 prompts/rebase-resolve.md 进 headless 路径:managed review PR
mergeable=CONFLICTING(base 落后)时,controller 在 PR worktree 起 git merge
--no-commit --no-ff origin/<integration>——干净则直接 commit+push,有冲突则派
rebase-resolve codex(隔离 worktree 内解+stage,禁 commit/push),收到
REBASE_RESOLVE_DONE 后 controller commit + safe_push 仅推 PR head。结果再过 CI+
review-gate 把关。新增 dispatch_pr_rebase_resolve / commit_push_resolved_pr_rebase
(controller_actions)+ wakeup_plan 投影 + wakeup_runner 应用。

安全:只动 refactor/iter<N>-* PR 分支,显式 guard 拒碰 integration/review_base,
diff-filter=U 验未解冲突才 commit,任何 abort 路径 git merge --abort 留干净 worktree,
幂等(已含 base / 解析在飞则 NOOP)。修 stale-base churn 致 loop 永久停滞(一个 PR
合了其它全 CONFLICTING 无人解)的根因。codex 全套件 1589 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: rebase_resolve_actions 投影前 enrich live mergeability(修生产 gap)

自主-resolve 投影读 item.mergeable 前未 enrich,但生产 GhItem 来自 snapshot
mergeable 为空 → 永远 skip → CONFLICTING PR 不投影 dispatch_pr_rebase_resolve →
loop 仍停滞。复用同文件 _with_live_mergeability(review_evidence_redispatch_actions
已用同模式)。补 mergeable-为空-需-live-fetch 的回归测试(原测试 mock 了 mergeable
未覆盖此生产路径)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: dispatch_pr_rebase_resolve kind 进 EXECUTABLE_ACTION_KINDS(end-to-end 可执行)

_close_projection_action 的 else 分支默认 status_only=True;rebase action 的 kind
stale-base-conflicting-pr 不在 EXECUTABLE_ACTION_KINDS → 永远 status_only,runner 不
apply,CONFLICTING PR 永不自主 resolve。加该 kind(+ commit_push completion kind 如需)
进集合;controller_action 已在 RUNNER_NAMED_HELPER_ACTIONS 故随即保持 executable。补
端到端 wakeup-plan pipeline 测试(原测试只测 rebase_resolve_actions 单函数,漏了 closed-
action-projection 的 status_only 关卡)。codex 全套件 1593 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: rebase-resolve commit/dispatch 投影 gate 在实际 worktree merge 态(止 stale-marker 噪音)

commit_push_resolved_pr_rebase 之前只凭持久 REBASE_RESOLVE_DONE marker 投影,worktree
已 commit+push(#549)或 abort(#550/#551)后 marker 仍在 → 每 tick fail-closed 噪音 +
反复 0-codex(zero_streak 触警)+ stale marker 挡 #550/#551 fresh resolve。现 gate:仅当
worktree 真有 merge-in-progress(MERGE_HEAD)且无 unmerged 才投 executable commit_push;
否则不投。并让 worktree clean + 仍 CONFLICTING 的 PR 重新拿 executable dispatch_pr_rebase_resolve
(stale DONE marker 不再永久压制)。补端到端测试。codex 全套件通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec  (#549)

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec

* 修复 PR #549 review r3:#502 label-purge 适配当前 label 代码(contract-tests + architect/tests reject)

fix codex round-3 applied-4:对齐 #502 遗留 label 兼容层 purge 与近期新增 label 代码,
修 contract-tests 失败 + architect/tests reject。改 labels.py + SKILL.md + test_wakeup_plan.py。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless review_gate ci_failed 死锁:reject→FIX 移到 ci/mergeability 检查前

_review_gate_decision 之前 ci_error/mergeability 检查在 reject>0→FIX 之前 → CI 红的 PR
即使 reviewer reject 也返回 WAIT_OR_REDISPATCH:ci_failed 干等,而 CI 不修不会绿 → 死锁
(#548/#549 都中,需手动派 fix 破解)。把 reject>0→FIX 移到 ci/mergeability 检查前
(仍在 reviewer-validity/head 检查之后)→ reject 时即使 CI 红也自主派 fix(fix 同解 reject+CI)。
MERGE/MERGE_WITH_COMMENTS 判定完全不变(仍需 ci-green + mergeable + reject=0 + approve>=1),
无误合并风险。补 test_wakeup_runner 端到端测试(reject+ci-red→FIX;reject=0+ci-red 仍 WAIT;
happy path MERGE 不变;stale-head+reject 仍 WAIT)。full suite 1600 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修正 review_gate 顺序:mergeability 检查移到 reject→FIX 之前(CONFLICTING 不并发 review/fix)

上一修复(a125d19)把 reject→FIX 移到 ci+mergeability 前,破了 ci_failed 死锁但也让
CONFLICTING+reject 的 PR 路由到 FIX → 与独立的 dispatch_pr_rebase_resolve 并发跑同一
worktree(#550 出现 98-file mid-merge + reviewer 并发)。把 mergeability_error 检查移到
reject→FIX 之前:CONFLICTING→WAIT(先 rebase-resolve,不并发 review/fix);MERGEABLE+
CI红+reject→FIX(死锁修复保留);ci_error 仍在 reject→FIX 后(纯 CI 红无 reject 才 WAIT)。
MERGE 判定不变。test_wakeup_runner 90 OK(+conflicting 用例)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es (#550)

* 实现 issue #498

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es

* PR #550 review-fix output

* 新增 patrol-inspector 巡检 issue intake (#551)

* 实现 issue #541

* PR #551 review-fix output

* PR #551 review-fix output

* 修复 PR #551 contract-tests:对齐 patrol 第8 daemon + safe_push/sync_dev 测试 host.env

#551 patrol 新增 patrol_inspector_daemon(第8 daemon)→ test_anti_stop_restart 期望 7→8;
test_controller_lib_safe_push / test_sync_dev 补 CONSENSUS_RND_HOST_ENV host.env 设置
(代码按 host-config contract 需 host.env locator,rebase-resolve 丢了 base 新测试版本)。
断言未削弱(daemon 数断言强化为8)。full discovery 1634 OK + sshx 13 OK。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 PR #551 contract-tests(clean-env):e2e fixture 设 META_ESCALATION_STUCK_HOURS 隔离 de-dup 测试

test_batch_and_per_task_lock_do_not_duplicate_spawn 在 clean env(CI)下失败:#506 meta-
escalation 因 fixture mock 态被判 stuck 而 fire,产出 repository-stalled RunnerResult 污染
de-dup 断言(expected [] got [RunnerResult])。fixture host.env+env 设 META_ESCALATION_STUCK_
HOURS=999999 禁该测试的 meta-escalation,聚焦 de-dup 行为。断言未削弱。clean discovery 全过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 publish-gap:implement readiness 用 git status --porcelain 判 staged diff

原 classify_implement_attempt / wakeup_runner publish 前用 git diff --quiet 只检测 unstaged
改动;worker 正确 git add -A 后 staged diff 被误判 empty_scoped_diff,导致完成的 implement
(如 #553 干净 EXIT=0 + 885 行真实 staged diff + 有效 title/body artifacts)永远出不了 PR,
wakeup_runner 对 children 反复空转 re-dispatch。改为先 git status --porcelain 判 staged/
unstaged/untracked 任一即 publish-ready,只有真干净才 fallback git diff。publish-time 建 PR
路径不变(不重蹈 #507 early-PR 空 commit/placeholder 死锁)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 patrol_inspector daemon 启动崩溃:DaemonHeartbeatLease 用构造函数非 from_env

#551 patrol.py daemon 分支调 DaemonHeartbeatLease.from_env()(不存在的方法)→
AttributeError 启动即崩,daemon 从未成功跑起来。改为 DaemonHeartbeatLease(
"patrol_inspector_daemon", ctx.repo_root),与 closed_label_reconciler/wakeup_runner
一致,心跳文件名匹配 restart 助手期待的 patrol_inspector_daemon.ts。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 publish-gap 残留层:duplicate-marker log 读 companion artifact + 取代 superseded spawn intent

层2 残留:implement worker 把 IMPLEMENT_DONE:issue-N:ok 在 log 里 echo 多次→
worker_markers 返回 duplicate_or_conflicting_log_marker fail-closed→classifier 当
markerless 且不查 companion artifact→无 completed-marker action→无 publish→stale
harness-spawn-intent:dispatch-consensus-implementation:N 残留致 pending_implement_intent。

修:(1) classify_implement_attempt / completed_marker_actions 遇 duplicate marker 时
narrow 读 companion .refactor-loop/runs/implement-*.md(仅 implement log,仅末 30 行恰好
1 个 IMPLEMENT_DONE:ok 才接受);(2) suppress_publish_superseded_implementation_spawn_intents:
仅当某 issue 已有 executable publish_implementation_output 才把对应 dispatch-consensus-
implementation spawn intent 抑制为 status_only(implementation_ready_to_publish)。
不重蹈 #507 死锁:只在 publish 已 ready 后抑制 spawn(不漏派)、publish 仍全验证(不提前/
重复)、wakeup-runner/publish 授权口径不变。live 验证 #553 现投影 executable publish。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #555 (#557)

* 修复 publish-gap 第3层:wakeup_runner clean_exit revalidation 对 duplicate-marker log 复用 artifact-fallback

pubgap2 修了 plan 侧 duplicate-marker artifact-fallback,但 wakeup_runner 的
_source_log_has_clean_marker(clean_exit_source_marker 预条件 revalidation)仍用严格
reader,对 #553 duplicate IMPLEMENT_DONE echo 返回 clean_exit_marker_missing→阻 publish。
改为严格 reader 优先,仅当 duplicate_or_conflicting_log_marker + is_implement_log +
_implement_run_artifact_done_marker 精确匹配 projected marker 才 fallback。复用 plan 侧
同一 helper,不弱化安全门(reviewer/release/rebase/非 implement/其它 fail reason 保持严格)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #553

* PR #561 review-fix output

* PR #561 remote-ci-fix output

* PR #561 review-fix output

* 收窄 restart daemon 权威到 owner-local 命令面 (#558)

* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+co…
loning added a commit that referenced this pull request Jun 6, 2026
* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。



* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。



* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。



* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。



* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。



* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions 309 通过。



* hotfix r12: run_once 不再让 spawn-batch starve drain-only lifecycle — ready PR headless merge,backlog 能 drain

根因(已核实):wakeup_plan 每 tick 把 SPAWN actions(implement intent + design-consensus #495/#496/#490/#491/#418,index 0-5)排在 lifecycle review_gate(#480/#473/#402,index 6-8)之前;run_once 旧逻辑 `if applied_spawns>0 and not is_spawn_action: break` → 只要派了任一 spawn,首个 lifecycle 即 break 整 tick。design-consensus 几乎总有 spawn 活 → review_gate/merge 永远 starve → #473(approve/approve/comment → MERGE_WITH_COMMENTS,MERGEABLE+CI 绿)永不 merge,active 数永不下降。

修法(最小,核心 dispatch loop):
- 引入 consumes_spawn_budget = is_spawn_action or _uses_spawn_budget(action);超 budget 时 `continue`(不 break)以便仍能抵达后续 drain-only lifecycle。
- _uses_spawn_budget:dispatch_reviewers=True、review_gate 仅当决策为 FIX(会派 fix worker)=True;否则 review_gate(MERGE/MERGE_WITH_COMMENTS)、close 等 drain-only=False → 不占 spawn budget、floor 填满后仍被评估执行。
- 保留 r6 的 spawn launch-failure break/retry 与 dispatch_design_consensus no-intents skip-and-continue;真值表/head-binding/CI-green/mergeable 安全语义不变。

结果:每 tick 既用 spawn 填满 floor,又评估 merge/close 等 drain-only lifecycle,backlog 能 drain。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions+pr_checks 309 通过;新增 test_wakeup_runner_lifecycle_review_gate_not_starved_after_spawn_batch。



* hotfix r13: 修 WakeupRunner._run_command 把 --repo 注入到 gh 子命令前致全部 gh 调用 malformed — review→merge 根因

根因(实测确认):_run_command 对所有 gh 命令在 full[1:1] 插 --repo(子命令之前)。gh 不接受 --repo 作 pre-subcommand 全局 flag,且 gh api 根本不吃 --repo(repo 在 URL):`gh --repo O/R api repos/O/R/pulls/473` → rc=1 "unknown flag: --repo"。于是 wakeup-runner 的每个 gh 调用都 malformed:CI 读(PrChecksProjection(runner=_run_command) 的 gh api pulls/check-runs)→ ci_unavailable:pull_api_failure;mergeability(gh pr view)→ mergeability_unavailable;live-state 等同理。→ review gate 永远读不到 CI/mergeable → #473(approve/approve/comment=MERGE_WITH_COMMENTS,绿)、#402#480 永不 headless 落地。r11 的 retry 只是重复同一 malformed 命令。直连 PrChecksProjection()/直连 gh 用的是 plain default runner(无注入)所以正常,掩盖了 bug。

最小修法:_run_command 仅对 `gh pr`/`gh issue` 注入 --repo,且放在子命令(及其 verb)之后的合法位置;`gh api` 完全不动;绝不 pre-subcommand 注入;已存在 --repo 则不重复。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+pr_checks+wakeup_plan+controller_actions 312 通过;新增 argv-shape 测试 + e2e(stub subprocess.run 拒绝 malformed `gh --repo ... api`,ready PR 仍 merge)。



* hotfix r14: managed draft PR ready-then-merge — review gate 不再硬挡 pr_draft

根因(r13 修好 gh 调用后浮现):review_gate 的 _review_gate_mergeability_error 把 isDraft=True 当 WAIT_OR_REDISPATCH:pr_draft 硬挡。但本 loop draft-until-consensus:PR 开为 draft 直到 review 共识,merge_pr 在决策 MERGE/MERGE_WITH_COMMENTS 时 ready-then-merge。于是绿 gate 的 managed draft(如 #473 approve/approve/comment)永远卡 pr_draft、永不 headless 落地。

最小修法:
- wakeup_runner:删除 mergeability 检查里的 isDraft→pr_draft 硬挡(仍挡 mergeable!=MERGEABLE,即 CONFLICTING/DIRTY)。
- controller_actions.merge_pr:对 live draft PR 先校验 crnd:lifecycle:managed 再 gh pr ready(非 managed draft 不 ready,写 CONTROLLER_ACTION_BLOCKED:target-not-managed 并返回 2);保留既有 ready-then-merge。
- 真值表/head-binding/CI-green/conflicting-blocks 安全语义不变;readying 仅限 managed PR。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan+pr_checks 316 通过;新增 managed-draft merge + 真实 plan→runner→controller ready-then-merge e2e + conflicting/非managed 安全用例。



* #409: 移除 .refactor-loop/host.env runtime fallback,CONSENSUS_RND_HOST_ENV 为唯一 host fact locator(缺失 fail-closed);迁移依赖 legacy fallback 的 test fixture (#473)

* hotfix r15 (sshx 共识 B 之一): 统一 gh argv 构造到单一 build_gh_argv helper — 防 r13 类 --repo bug 复发

sshx 一致共识 B 的硬化第1步:把分散重复的 gh --repo 处理收口到 codex_refactor_loop/gh_invoke.py 的 build_gh_argv(slug, argv):gh api 永不加 --repo(repo 在 URL);gh pr/issue 仅在 subcommand 之后、缺失时加 --repo <slug>;绝不 pre-subcommand。wakeup_runner._run_command / ControllerActions.gh / PrChecksProjection 三处 API 调用全部改走该 helper,删除各自的内联 --repo 启发式。行为保持不变(含 r13 修复)。

验证:characterization + source-regression 锁在 test_gh_invoke.py(9 测试);controller 独立重跑 test_gh_invoke+pr_checks+wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan 326 通过;pr_checks 直跑 --help 兼容。

注:这是硬化(防复发),不直接提升并发;并发瓶颈在上游 implement→publish 阶段,接下来单独处理。



* hotfix r16 (sshx 共识): 打通 implement→publish 解锁并发瓶颈 — markerless/stale implement 重派 + 安全门控发布

sshx codex-cli triplet 共识(minimal/structural/delete + meta-judge):10 个 design-solving issue 已达成共识但卡在 implement→publish(implement 早跑过却 markerless/未提交/过期 base/没 PR;dispatch_consensus_implementation 被 local_iter_branch 抑制、publish 被 verified_pr_head_unavailable 抑制)→ 无新可派工作 → 并发 ~1。

修法(wakeup_plan/wakeup_runner/controller_actions/git.py):
- success-aware 重派:implement 分支/worktree 存在但无 valid clean IMPLEMENT_DONE:ok marker(markerless/failed)或 base 过期 → 重派;fresh_safe_worktree 把 canonical worktree reset/recreate 到当前 origin/$INTEGRATION_BRANCH;仅 genuine in-flight / 已有干净 PR / 待发布 clean marker 才抑制。
- 发布门控(严防误发 stale/wrong-scope):publish_implementation_output 仅在 canonical identity(refactor/iter<issue>-<candidate> + worktree 实际分支匹配)+ fresh integration base(merge-base==origin/integration,过期 base block)+ managed open issue + 无重复 PR + 非空 scoped diff 时,commit→push→open PR→派 reviewers;否则 block。
- wakeup_plan 用 canonical_implementation_identity/single_linked_managed_issue/clean_scoped_diff 替代 verified_pr_head 抑制。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 330 通过。

已知待修(follow-up):worker 把 PR title/body/commit 文案改成英文,违反「GitHub artifact 中文」策略,下一 commit 恢复中文。



* hotfix r17: fresh consensus-implement 重派前清除 terminal 非可发布 implement log — 让卡住的 implement 真正启动

承接 r16:r16 让 markerless/stale implement 重派(reset worktree),但旧的 EXIT=1/markerless implement log 仍占 spawn 的 target_log_absent 前置 → fresh implement 不启动(同一类「按存在抑制」,implement-spawn-log 层)。

修法(controller_actions,success-aware):fresh consensus-implementation dispatch 写 spawn intent 前,仅清除 terminal 非可发布 implement log(EXIT!=0 失败 / EXIT=0 无 IMPLEMENT_DONE:ok marker);保留 genuinely in-flight(无 EXIT)与 clean publish-ready(EXIT=0 + 干净 marker)log 不动。于是卡住的 markerless/failed implement 重派后能真正 launch、跑在 fresh base、产出干净 marker → r16 门控发布。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 333 通过。

设计说明:并发瓶颈用确定性逻辑修对(ready=clean EXIT=0+marker;parallel=scope_paths 不相交),不引入 LLM-in-loop 分发判断(daemon-first;sshx codex 三人组一致 revise:LLM 最多 shadow-mode,不入决策回路)。



* hotfix r18: implement-lifecycle 收敛为单一 success-aware 谓词 + runner 路径自清陈旧 log — headless 自愈,不再需手动清 log

承接 r16/r17(r17 把清 log 放进被抑制的 dispatch 路径,从没执行)。新增 implement_lifecycle.py 单一事实源 classify_implement_attempt → in_flight | publish_ready | redispatch,plan/runner/controller 共用:
- runner spawn-apply 路径 _spawn_log_suppresses_retry 仅在 in_flight|publish_ready 时抑制;redispatch(EXIT!=0/markerless/stale-base) 不抑制且 _clear_redispatchable_spawn_log 在 spawn 实际应用处清掉陈旧终态 log → fresh implement 真启动(修 r17 misplacement,免手动清)。
- publish 仅 publish_ready(clean IMPLEMENT_DONE:ok + canonical identity + fresh base + 非空 scoped diff);clean-marker 但 stale-base 改 redispatch 而非死锁(#421 edge)。
- 确定性逻辑(非 LLM-in-loop;daemon-first);merge-gate/#191/#322/#396 安全语义不变。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 339 通过。



* 修复 phase9-router triplet-evidence-invalid 误判致 headless design-consensus wedge

solver prompt 注入的 issue source snapshot 含上一轮 design-consensus 的
audit-trail(peer solver log 路径)时,_peer_solver_reference_violation
扫描整个 prompt 误判为 peer-isolation 违规,fail-closed 拒派 meta-judge,
使所有 body 含历史 consensus 记录的 issue 永久 wedge。

修复:peer-isolation 扫描只覆盖 router-controlled 区域,剥离
'## Issue source snapshot' 到 '## Full solver template' 之间的 issue
作者内容;router header / solver template 注入的真实 peer 引用仍拦截。
加两个 behavior test 覆盖 snapshot-排除 与 router-区域-仍拦截。

dogfood headless 实测:reload 后 418/437/474/490/491/493/494/495 全部
恢复 solver→judge→consensus 自驱,#494 已自驱到 implement。



* CLAUDE.md: 加 consensus-rnd:foundational-invariants sentinel block

dogfood bootstrap 的 check-project-rules probe 要求 PROJECT_RULES 含此
fixed-point block;缺失时 probe fail-closed 阻断 headless restart。内容
为 probe 生成的 canonical FI-001~007,镜像既有设计哲学,不引入新约束。



* 修复 markerless implement 致 publish 卡死的 headless gap

implement worker 干净退出(EXIT=0)但把 IMPLEMENT_DONE marker 只写进 run
artifact(runs/implement-issue-<id>.md)而非 log 末尾时(codex stdout marker
落点不可靠),completed_marker_actions 只扫 log marker → markerless → 不生成
publish action → design→implement→PR 链卡在 implement 后。实测 #421:EXIT=0
+ artifact 有 IMPLEMENT_DONE:issue-421:ok + 9 文件 staged,却无 PR、label 仍
停在 design-solving。

修复:对 clean-exit 的 implement-issue log,log markerless 时 fallback 读取
run artifact 末尾的 IMPLEMENT_DONE marker,复用 review verdict 已有的
artifact-first 模式。窄作用域(仅 implement-issue + clean-exit),配 2 个
behavior test;全套 wakeup_plan 138 tests green。



* 补全 markerless implement publish:revalidation 也读 run artifact marker

8aeea89 修了 wakeup_plan detection 端,但 wakeup-runner 的 source-marker
revalidation(_source_log_has_clean_marker)仍只扫 log,markerless implement
publish 仍被 reject(clean_exit_marker_missing)。补全:revalidation 对
clean-exit implement-issue log 在 log markerless 时 fallback 读
runs/implement-issue-<id>.md 的 marker,与 detection 端一致;配 behavior test,
全套 wakeup_runner 76 tests green。

注:dogfood 实测确认 markerless 是系统性病根(还影响 readiness 重派、review
verdict 等多处),应走系统性统一(见 #491 日志/observability 与后续 marker-reading
收口);本 commit 只补 implement publish 这条链。



* 日志详细化:wakeup-runner tick 显示全状态计数 + 被掩盖的 blocked/skipped 详情

旧 _wakeup_tick_action 只看 results[0],一个 tick 处理多 action 时 blocked(如
publish 失败)被成功的 spawn 掩盖、完全不可见;graphql-backoff 固定显示误导的
'remaining=unknown'。dogfood 调试时这逼得每次翻 ledger 才知道真实发生了什么。

改:tick log 显示 [applied=N,blocked=M,...] 全状态计数 + 被掩盖的 blocked/skipped
具体 reason+action(graphql-backoff 作整-tick 门控单独报、去掉 unknown);dispatched
headline 保留。更新 test 反映可见性提升,全套 wakeup_runner 76 tests green。



* 补全 markerless implement 第三环:readiness 谓词读 run artifact marker

classify_implement_attempt(r18 单一 success-aware 谓词)只扫 log 找
IMPLEMENT_DONE:ok,markerless log(marker 落 artifact)→ redispatch:markerless →
readiness 不 suppress → 重派覆盖已完成工作(dogfood 实测 #421 重派 4 次、#493
IMPLEMENT_DONE:ok→重派→:partial 工作丢失)。

补全:markerless log 时 fallback 读 runs/implement-<cluster>.md 的
IMPLEMENT_DONE:ok,与 detection(8aeea89)/revalidation(dfacc64)一致。窄作用域 +
r17/r18 兼容:只接受 :ok,partial/失败/真 markerless(无 artifact)仍 redispatch
recovery — 现有 markerless-redispatch test(wakeup_plan/wakeup_runner/
controller_actions 共 304 tests)全绿,新增 2 behavior test。

至此 implement→PR 的 markerless 三环(detection/revalidation/readiness)打通;
review 链 markerless 与系统性统一抽象交 #499 共识。



* #500: design-consensus 编排重设计 — phase9-router 唯一派发 owner,删 wakeup-runner 双重派发

落地 #500 r4 consensus(structural framing,no-new-schema):
- phase9-router 成为唯一 design-consensus worker intent owner,新增
  META_RESOLVED:re-design → marker.round+1 三路 solver route
- 删除 wakeup-runner 的 dispatch_design_consensus(消除双重派发 helper_exit:3)
- wakeup-runner 只保留 closed action apply(drop→close、consensus→implement)
- dispatch_consensus_implementation readiness 后转 crnd:phase:implementing
- 无新增 schema(复用 HARNESS_SPAWN_INTENT)

修复 headless P0:reflector META_RESOLVED 无 consumer + phase9-router/wakeup-runner
双重派发致 0-codex 死锁。14 文件 +207/-282;verification 471 tests 全绿。

共识由 controller 手动驱动 design-consensus r1→r4 达成(daemon 停止期间)。



* #501 fix r1: 补 dispatch_consensus_implementation label-transition failure-branch test

tests reviewer reject:新增 label transition(gh issue edit→implementing)只测 success
path,缺 gh issue edit 返回 nonzero 时 dispatch stop before worktree/render/intent 的
failure-branch test。本 fix 补该测试。



* 修复 headless 死锁:label 移除集只留 canonical crnd:*,删除历史 alias

gh issue/pr edit --remove-label 会因仓库不存在的 label 整条 rc=1 失败。
ISSUE_LABELS_REMOVE/PR_LABELS_REMOVE 含 cleanup_aliases(emoji/legacy 名),
仓库未维护这些历史 label,导致 _move_issue_to_implementing_phase 永久失败,
consensus→implement 派发卡死、wakeup_runner 0 codex 自驱死锁。

按 maintainer 指令删除历史 label 兼容(不再管历史标签):移除集只列
canonical crnd:* phase/human/stuck label。新增 source-regression 锁定
两集 canonical-only、无 alias。



* 修复 #500 回归:phase9-router 生产 ctx 丢失 GH_REPO_SLUG 致 design-consensus intake 全死

#500(e733b1a)把 Phase9Router.__init__ 的 ctx 构造从
`LoopContext.load(repo_root=repo_root)` 改成
`LoopContext.load(repo_root=repo_root, env={"REPO_ROOT": str(repo_root)})`。
受限 env 不读 os.environ,使 daemon(经 source host.env 启动)的 ctx
gh_repo_slug=None → `_open_design_consensus_issues` 第一行 fail-closed 返回 []
→ DesignConsensusIssueIntake 静默永不派 → headless 无法为任何 issue 启动
design-consensus;`_require_open_source_issue` 也因无 slug 失败(marker route
如 #490 redesign 卡在 phase9-source-state-unavailable)。

修复:revert 为 `LoopContext.load(repo_root=repo_root)`,读进程环境解析 host facts。
测试一律用 `Phase9Router(ctx=...)` 显式 ctx,不依赖受限 env;新增回归测试锁定
生产 repo_root 构造路径解析 GH_REPO_SLUG。



* 加 STALE_REVIVAL_HOURS:>阈值未推进的 stuck implement 自动 re-trigger(env 可配,默认 3h)

headless 下 partial/failed/markerless 的 implement log 会让已排队的
dispatch-consensus-implementation spawn intent 永久卡在 runner 的
target_log_absent 前置(清 log 的 dispatch_consensus_implementation 又被
pending_implement_intent 抑制)→ stuck implement 不会自愈(如 #421/494/493/474/498
的 10h partial-wedge)。

新增 host-tunable STALE_REVIVAL_HOURS(默认 3,非正/非法回落 3h)。wakeup_plan
投影 implement spawn intent 时,若目标 implement log 是 redispatchable
(partial/failed/markerless/stale-base)且 mtime 已超阈值,清掉它 →
target_log_absent 通过 → implement 自动重派。安全闸:in-flight(无终止 EXIT)永不清、
publish-ready(:ok+diff)不清、age-gate 防误清刚跑完的。

env 已登记进 SKILL.md host env surface matrix + host.env.example;5 个 behavior
test + matrix↔example 对称测试覆盖。



* 扩展 stale-revival 覆盖死 codex:in_flight 无 EXIT 且 >阈值 + 不在存活清单 也 re-trigger

最常见的 headless wedge 是 codex/supervisor 中途死亡(如 daemon 被 kill 截断),
log 永远停在 in_flight(无终止 EXIT)→ classify 永判 in_flight → 永不 redispatch。
之前只清 redispatchable(partial/failed/markerless)log,漏了这半边。

现在 _revive_stale_redispatchable_implement_log 在 log mtime 超阈值时,先按
redispatchable 清;否则若 classify 为 in_flight 且 monitor 存活清单里无该 log 的
活进程,则判定为死 worker 清掉。安全性:spawn-codex 的 no-output stall 窗口远小于
默认 3h,故 >阈值仍 in_flight 的 log 必是死 supervisor;再加 monitor 存活校验
双保险,绝不杀活 codex。新增 3 个 behavior test(死 codex revive / fresh 不碰 /
活进程不碰)。



* 加手动 trigger:consensus-rnd-cli revive-implements(立即 re-trigger 卡住的 implement,不等阈值)

_revive_stale_redispatchable_implement_log 加 force 参数:跳过 stale_revival_seconds()
age gate,但 in_flight log 在 force 下必须经 monitor 存活校验证明无活进程才清(绝不杀
正在跑的 codex)。新增 force_revive_stuck_implements() 扫所有 implement-issue-*.log
强制 revive,和新 CLI 命令 revive-implements(authority delete-log)。auto 路径
force=False 不变。新增 4 个 behavior test。



* 修 env 泄漏:测试套件 import 时隔离 ambient host.env(worktree 里跑 TEST_CMD 不再假失败)

daemon spawn 的 implement worker 在 worktree 里跑完整 TEST_CMD 时,继承的相对
CONSENSUS_RND_HOST_ENV=.config/consensus-rnd/host.env 泄漏进 temp-repo
LoopContext.load(repo_root=tmp) → 解析成 tmp/.config/... 不存在 → 假
LoopContextError(实测 concurrency_monitor 48 + restart_daemons 23 + … ≈151 errors)
→ 全套永不绿 → implement 永远 :partial → 进不了 PR。

unittest discover 在 collection 阶段先 import 所有 test_*.py 再跑;新增
test_aaa_host_env_isolation.py(字母序最先)在 import 时 pop 掉 host 注入变量,
全套在任何测试 run 前即隔离。验证:full discover 设 locator 跑 → exit 0 全绿
(此前 同条件 151 errors);targeted before/after 证 48/23/1 errors → OK。
纯测试模块,不碰 production/daemon。



* 修 markerless keystone:solver/judge marker 加 companion-artifact fallback

solver/judge codex 有时 EXIT=0 但 SOLVER_DONE/META_JUDGE_DONE marker 只落 run
artifact、没在 log 末尾,导致 phase9-router 判 triplet 不完整、永不派 judge,
design-consensus 轮卡死(实测 #505 r1 structural 214 次嵌入、0 次行首)。

把已有的 implement artifact-marker fallback 扩到 solver/judge:clean-exit log
末尾无独立 marker 时,从 companion run artifact runs/<log-stem>.md 兜底读。纯
additive(log 有 marker 时行为不变)、prefix-scoped、精确 filename regex、复用
安全的独立 marker 提取(不信嵌入/echo)。不削弱共识(仍要 3 marked solver +
judge,只让 marker 来源更稳健)。phase9/router.py + wakeup_plan.py + behavior +
source-regression tests;full suite 1367 green。



* 修 publish stale-base 无恢复 + 停 :ok churn:让 implementing 能发出 draft PR

implement :ok 但 worktree base 落后 origin/$INTEGRATION_BRANCH 时,publish 原本硬
block(publish_implementation_stale_base)且永不恢复;stale-revival 又把 stale-base
的 :ok implement 当 redispatchable 反复重派同一 stale worktree → 无限 churn 占满
floor、长时间零正式 PR(implement→首个 PR 永远开不出)。

改为:publish 前在 worktree merge origin/$INTEGRATION_BRANCH 恢复 base(冲突则
merge --abort + 明确 reason 交既有 resolver/re-dispatch);clean `:ok` 不再被
stale-revival churn(终态成功走 publish-with-recovery,不重跑);无 open PR 的 :ok
创建 draft PR(per #300 共识前 draft)+ Closes #N。controller 仍拥有 git topology,
worker 不 commit/push,不绕 review-gate/merge 真值表。controller_actions.py +
wakeup_plan.py + wakeup_runner.py + behavior/source-regression tests;full suite
1374 green。



* 修 markerless implement:EXIT=0+真diff 无干净 marker 时合成 publish 候选,止 stale-revival 空重派死循环

publish build/test 闸做安全网。



* 修 publish 顺序 bug + merge 失败派 codex 兜底 resolver:先 commit worker diff 再 merge fresh base,真冲突不 wedge 改派 resolver,幂等续跑

空判据改 git diff HEAD;顺带修 wakeup_plan stale-suppression 同类 git diff 问题。



* 实现 issue #504 (#519)

* 修 headless review-fix prompt 渲染不全:绑定全部 placeholder(PR_NUMBER/标题/轮次/分支/REVIEW_*_PATH 等),解锁 reject PR 的 fix→merge

之前 headless _dispatch_review_fix 只绑 FIX_OUTPUT_PATH,其余 ${} 未解析致 fix codex 读不到 reject 证据。



* 实现 issue #496 (#520)

* 修 review-fix codex 派到 main 的 cd bug:改在 PR worktree 跑,worktree 缺失 fail-closed

之前 _dispatch_review_fix cd=repo_root → fix 改 main(污染 daemon checkout)且不落 PR 分支(reject PR 永不 merge)。



* 实现 issue #508 (#523)

* 修 wakeup-plan action 排序:review_gate/publish 排到新工作 spawn 前,解 spawn-budget 饿死→reject PR 可被 fix→merge



* CLAUDE.md 加宪法工程规则:异常必抛出+记可诊断日志严禁吞掉/静默;测试必断言真实行为禁无意义测试(maintainer 指令)



* 实现 issue #503 (#521)

* 增加通用工程基本规则,明确面向对象设计要求及实现细则

* 实现 issue #514 (#524)

* 完善通用面向对象设计准则,增加核心原则与实现层细则

* 实现 issue #494 (#526)

* 实现 issue #517 (#528)

* 实现 issue #505 (#510)

* 实现 issue #505

* #510 fix r1:补 phase9-router 行为测试覆盖(应对 tests reviewer reject)



---------



* 修复 headless FIX_DONE 不提交 fix 输出 gap:wakeup-runner 在 FIX_DONE re-review 前先 commit+push fix worktree

headless 下 fix codex 产出 FIX_DONE 但 worker 从不 commit,FIX_DONE 直接路由 dispatch_reviewers,
fix 输出永远留在 worktree 未提交,reviewers 永远审旧 head,reject 不收敛,阻断所有需 fix 轮的 PR
review→merge。镜像 interactive controller:FIX_DONE 源的 dispatch_reviewers 前,若 fix worktree
dirty 则 git add+commit+safe_push,clean 则 no-op。附 2 个 behavior test(dirty 提交/clean 跳过)。



* 实现 issue #491 (#531)

* 实现 issue #490 (#529)

* 实现 issue #490

* 实现 issue #490

* PR #529 review-fix output

* 实现 issue #499 (#512)

* 实现 issue #499

* PR #512 review-fix output

* 实现 issue #474 (#532)

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* PR #532 review-fix output

* 实现 issue #476 (#518)

* 实现 issue #476

* PR #518 review-fix output

* 实现 issue #509 (#527)

* 实现 issue #509

* 实现 issue #509

* spawn-claim recycle 改用 artifact-aware terminal marker:companion log 被 24h retention 删除后,已完成任务的 claim 仍可回收(读 runs/ artifact),不再永久阻断重派;running 任务无终止 marker 仍不回收(防 double-spawn)

* 实现 issue #421:发行前 clean-room 集成测试制度 (#534)

* 实现 issue #421

* rebase #421 onto fresh integration:解决 test_cli_command_router 冲突 + 校验

* 实现 issue #493:测试纪律修宪(behavior-first) (#535)

* 实现 issue #493

* rebase #493 onto fresh integration:解决冲突 + 校验

* PR #535 review-fix r1:addressed tests+quality reject(behavior-first test 调整)

* 实现 issue #506 (#536)

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* PR #536 review-fix output

* churn 根治:wakeup-plan 给 consensus-impl spawn-intent 套 open_closing_pr/terminal/in-flight 抑制(对齐 dispatch_consensus_implementation),已有 PR 的 issue 不再被重派 implement

* 实现 issue #507 (#525)

* 实现 issue #507

* 实现 issue #507

* PR #525 review-fix output

* 实现 issue #516 (#530)

* 实现 issue #516

* 实现 issue #516

* #530 fix r1:补 ManagedWorkSnapshot fetch-failure stale-cache fallback 行为测试(应对 tests reviewer reject)

* PR #530 review-fix output

* PR #530 review-fix r2:typed ManagedWorkItem projection(addresses architect 类型边界 reject + tests + contract-tests)

* PR #530 review-fix r3:anchor ManagedWorkSnapshot read surface in authorization mirror + cross-artifact source-regression(addresses architect governance reject)

* PR #530 review-fix r4:add canonical+legacy managed-label discovery regression test(addresses tests reject)

* 修复 worker marker reader 误判相同重复 marker 为冲突

codex 常把终止 marker 回显 2-3 次(含 diff + 前缀行),导致
read_worker_terminal_marker 返回 duplicate_or_conflicting,review 真值表
永不收敛、所有 headless review→merge 卡死。改为:相同重复 marker 折叠为
有效,仅当存在 2+ 个不同 marker 值才判 duplicate_or_conflicting。
覆盖 _last_final_marker / _sentinel_adjacent_marker /
_marker_from_companion_artifact,保留 malformed 与 foreign-prefix 检测。



* Reserve implementation PR for issue #537 (#540)

⟦AI:AUTO-LOOP⟧

* 实现 issue #511 (#522)

* 实现 issue #511

* PR #522 review-fix output

* PR #522 review-fix output

* 移除误入 PR 的 .refactor-loop 运行 artifact(architect r8 reject)

resolve-pr522-merge.md 是一次性合并解决 summary,属生成物,不应进 durable diff
(CLAUDE.md「生成物不当事实源」)。解决说明保留在 commit message / PR body。



---------



* 修复早期 PR reservation 崩溃(#511 回归,阻断所有 implement 派发)

_reserve_implementation_pr 用 worker 富正文路径开 reservation PR,但该文件在
reservation 时尚不存在 → FileNotFoundError(未被 except RuntimeError 捕获)→
wakeup-runner tick 崩溃 → 任何 consensus issue 无法 implement → loop P0 wedge。
修复:reservation 前若 body 缺失则写占位正文(## issue #N 实现 + Closes + sentinel,
publish 会拒占位逼 worker 产真正文);reservation 幂等(已有 open PR 直接返回;
已有 remote head 则 reset 到 integration + force-with-lease push);捕获 OSError。



* Reserve implementation PR for issue #543 (#544)

⟦AI:AUTO-LOOP⟧

* Reserve implementation PR for issue #541 (#546)

⟦AI:AUTO-LOOP⟧

* revert early-PR reservation(#507):不再开空占位 PR,publish 出真内容才开 PR

dispatch_consensus_implementation 不再 reserve/开 PR;publish_implementation_output
恢复 pre-#507 行为——implement 出非空 diff 才 commit+push+open_pr_with_label(用 worker
真 title/body,验证非占位);空 diff 不开 PR、不 merge、不关 issue。删除占位机制
(_reserve_implementation_pr / _placeholder_*),改 wakeup_plan/runner 的 early_pr_missing 投影。
根因:空占位 PR 被 reviewer 在 implement publish 前空合,假性关闭 #537/#541/#543。
全量套件 1496 passed。



* 实现 issue #542:删除 redispatch payload 冗余 head_sha (#547)

移除 review redispatch 的重复 head_sha payload

* hotfix: stale consensus-implement intent 指向已删 worktree 不再 suppress fresh re-dispatch

consensus_implementation_suppressed_reason 的 pending_implement_intent 分支增加 worktree 存在性
守卫(接入既有 _canonical_consensus_worktree_exists):仅当 stale pending intent 的 canonical
worktree 仍存在时才 suppress。revert early-PR reservation(#507)后,#537/#541/#543 的 pending
implement intent 指向已删除 worktree,旧逻辑 suppress fresh re-dispatch,而 wakeup-runner 不断把
stale intent spawn 进死 cd 致 os error 2 / EXIT=1 死循环,阻断 consensus→implement 自主链路。
现 worktree 缺失即放行 fresh dispatch 重建 worktree。

补 test_wakeup_plan(worktree 缺失不 suppress / worktree 存在仍 suppress)+ 更新
test_controller_actions 锁旧行为的 subTest(pending case 建 canonical worktree 以保留
reject-before-fresh_safe_worktree 意图)。全套件 1557 passed。



* hotfix: spawn-claim lock 持有者 pid 已死即可回收(自愈,防 cleared-log 永久 HELD)

_existing_claim_is_recyclable 增加 pid-liveness 回退:当 lock 记录的持有者 pid 已死(os.kill
pid 0 抛 ProcessLookupError)时即可回收,保留既有 terminal-marker 回收与 live-spawn 保护
(pid 存活+无 marker 仍不回收)+ metadata-mismatch fail-closed。根因:implement 失败(EXIT=1)
留 stale lock,dispatch_consensus_implementation 重派时清掉 log → #490 spawn-claim 只在 log 有
EXIT= 时回收 → cleared log 无 marker → 死进程 lock 无法回收 → SPAWN_CLAIM_HELD 永久死锁,
阻断 consensus→implement 重派(#537/#541/#543)。补 7 个 behavior test。全套件 1560 passed。



* hotfix: publish_implementation_output 接受 worker 已 commit 的实现 diff

_require_publish_implementation_diff 之前只看 git diff HEAD --quiet(未提交改动),
worker 一旦自己 commit(在自己分支上,隔离无害)工作区就 clean → 误判 no_diff → 不开 PR。
现改为:有未提交改动 OR HEAD 相对 integration base 有 committed delta(merge-base..HEAD 非空)
即视为有 diff 可发;_commit_publish_implementation_diff 在工作区已 clean(worker 已 commit)时
跳过提交返回成功,不再误报 publish_commit_failed。修 #541 类 worker-commit→no_diff→无 PR+
daemon 重复 dispatch。补 behavior test。codex 全套件 DISCOVER_STATUS:0 通过。



* 实现 issue #437: .refactor-loop 历史生成物与陈旧 worktree 的有界清理机制 (#548)

* #437: 新增 canonical RuntimeRetention owner,log-retention 降为一版 alias;清理覆盖 generated files+pending-events compaction+stale worktree;CLAUDE.md 加 #437 narrow carveout

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* hotfix: CONFLICTING managed review PR 的 stale-base 冲突自主 resolve

接线既有但孤儿的 prompts/rebase-resolve.md 进 headless 路径:managed review PR
mergeable=CONFLICTING(base 落后)时,controller 在 PR worktree 起 git merge
--no-commit --no-ff origin/<integration>——干净则直接 commit+push,有冲突则派
rebase-resolve codex(隔离 worktree 内解+stage,禁 commit/push),收到
REBASE_RESOLVE_DONE 后 controller commit + safe_push 仅推 PR head。结果再过 CI+
review-gate 把关。新增 dispatch_pr_rebase_resolve / commit_push_resolved_pr_rebase
(controller_actions)+ wakeup_plan 投影 + wakeup_runner 应用。

安全:只动 refactor/iter<N>-* PR 分支,显式 guard 拒碰 integration/review_base,
diff-filter=U 验未解冲突才 commit,任何 abort 路径 git merge --abort 留干净 worktree,
幂等(已含 base / 解析在飞则 NOOP)。修 stale-base churn 致 loop 永久停滞(一个 PR
合了其它全 CONFLICTING 无人解)的根因。codex 全套件 1589 passed。



* hotfix: rebase_resolve_actions 投影前 enrich live mergeability(修生产 gap)

自主-resolve 投影读 item.mergeable 前未 enrich,但生产 GhItem 来自 snapshot
mergeable 为空 → 永远 skip → CONFLICTING PR 不投影 dispatch_pr_rebase_resolve →
loop 仍停滞。复用同文件 _with_live_mergeability(review_evidence_redispatch_actions
已用同模式)。补 mergeable-为空-需-live-fetch 的回归测试(原测试 mock 了 mergeable
未覆盖此生产路径)。



* hotfix: dispatch_pr_rebase_resolve kind 进 EXECUTABLE_ACTION_KINDS(end-to-end 可执行)

_close_projection_action 的 else 分支默认 status_only=True;rebase action 的 kind
stale-base-conflicting-pr 不在 EXECUTABLE_ACTION_KINDS → 永远 status_only,runner 不
apply,CONFLICTING PR 永不自主 resolve。加该 kind(+ commit_push completion kind 如需)
进集合;controller_action 已在 RUNNER_NAMED_HELPER_ACTIONS 故随即保持 executable。补
端到端 wakeup-plan pipeline 测试(原测试只测 rebase_resolve_actions 单函数,漏了 closed-
action-projection 的 status_only 关卡)。codex 全套件 1593 passed。



* hotfix: rebase-resolve commit/dispatch 投影 gate 在实际 worktree merge 态(止 stale-marker 噪音)

commit_push_resolved_pr_rebase 之前只凭持久 REBASE_RESOLVE_DONE marker 投影,worktree
已 commit+push(#549)或 abort(#550/#551)后 marker 仍在 → 每 tick fail-closed 噪音 +
反复 0-codex(zero_streak 触警)+ stale marker 挡 #550/#551 fresh resolve。现 gate:仅当
worktree 真有 merge-in-progress(MERGE_HEAD)且无 unmerged 才投 executable commit_push;
否则不投。并让 worktree clean + 仍 CONFLICTING 的 PR 重新拿 executable dispatch_pr_rebase_resolve
(stale DONE marker 不再永久压制)。补端到端测试。codex 全套件通过。



* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec  (#549)

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec

* 修复 PR #549 review r3:#502 label-purge 适配当前 label 代码(contract-tests + architect/tests reject)

fix codex round-3 applied-4:对齐 #502 遗留 label 兼容层 purge 与近期新增 label 代码,
修 contract-tests 失败 + architect/tests reject。改 labels.py + SKILL.md + test_wakeup_plan.py。



---------



* 修复 headless review_gate ci_failed 死锁:reject→FIX 移到 ci/mergeability 检查前

_review_gate_decision 之前 ci_error/mergeability 检查在 reject>0→FIX 之前 → CI 红的 PR
即使 reviewer reject 也返回 WAIT_OR_REDISPATCH:ci_failed 干等,而 CI 不修不会绿 → 死锁
(#548/#549 都中,需手动派 fix 破解)。把 reject>0→FIX 移到 ci/mergeability 检查前
(仍在 reviewer-validity/head 检查之后)→ reject 时即使 CI 红也自主派 fix(fix 同解 reject+CI)。
MERGE/MERGE_WITH_COMMENTS 判定完全不变(仍需 ci-green + mergeable + reject=0 + approve>=1),
无误合并风险。补 test_wakeup_runner 端到端测试(reject+ci-red→FIX;reject=0+ci-red 仍 WAIT;
happy path MERGE 不变;stale-head+reject 仍 WAIT)。full suite 1600 passed。



* 修正 review_gate 顺序:mergeability 检查移到 reject→FIX 之前(CONFLICTING 不并发 review/fix)

上一修复(a125d19)把 reject→FIX 移到 ci+mergeability 前,破了 ci_failed 死锁但也让
CONFLICTING+reject 的 PR 路由到 FIX → 与独立的 dispatch_pr_rebase_resolve 并发跑同一
worktree(#550 出现 98-file mid-merge + reviewer 并发)。把 mergeability_error 检查移到
reject→FIX 之前:CONFLICTING→WAIT(先 rebase-resolve,不并发 review/fix);MERGEABLE+
CI红+reject→FIX(死锁修复保留);ci_error 仍在 reject→FIX 后(纯 CI 红无 reject 才 WAIT)。
MERGE 判定不变。test_wakeup_runner 90 OK(+conflicting 用例)。



* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es (#550)

* 实现 issue #498

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es

* PR #550 review-fix output

* 新增 patrol-inspector 巡检 issue intake (#551)

* 实现 issue #541

* PR #551 review-fix output

* PR #551 review-fix output

* 修复 PR #551 contract-tests:对齐 patrol 第8 daemon + safe_push/sync_dev 测试 host.env

#551 patrol 新增 patrol_inspector_daemon(第8 daemon)→ test_anti_stop_restart 期望 7→8;
test_controller_lib_safe_push / test_sync_dev 补 CONSENSUS_RND_HOST_ENV host.env 设置
(代码按 host-config contract 需 host.env locator,rebase-resolve 丢了 base 新测试版本)。
断言未削弱(daemon 数断言强化为8)。full discovery 1634 OK + sshx 13 OK。



* 修复 PR #551 contract-tests(clean-env):e2e fixture 设 META_ESCALATION_STUCK_HOURS 隔离 de-dup 测试

test_batch_and_per_task_lock_do_not_duplicate_spawn 在 clean env(CI)下失败:#506 meta-
escalation 因 fixture mock 态被判 stuck 而 fire,产出 repository-stalled RunnerResult 污染
de-dup 断言(expected [] got [RunnerResult])。fixture host.env+env 设 META_ESCALATION_STUCK_
HOURS=999999 禁该测试的 meta-escalation,聚焦 de-dup 行为。断言未削弱。clean discovery 全过。



---------



* 修复 publish-gap:implement readiness 用 git status --porcelain 判 staged diff

原 classify_implement_attempt / wakeup_runner publish 前用 git diff --quiet 只检测 unstaged
改动;worker 正确 git add -A 后 staged diff 被误判 empty_scoped_diff,导致完成的 implement
(如 #553 干净 EXIT=0 + 885 行真实 staged diff + 有效 title/body artifacts)永远出不了 PR,
wakeup_runner 对 children 反复空转 re-dispatch。改为先 git status --porcelain 判 staged/
unstaged/untracked 任一即 publish-ready,只有真干净才 fallback git diff。publish-time 建 PR
路径不变(不重蹈 #507 early-PR 空 commit/placeholder 死锁)。



* 修复 patrol_inspector daemon 启动崩溃:DaemonHeartbeatLease 用构造函数非 from_env

#551 patrol.py daemon 分支调 DaemonHeartbeatLease.from_env()(不存在的方法)→
AttributeError 启动即崩,daemon 从未成功跑起来。改为 DaemonHeartbeatLease(
"patrol_inspector_daemon", ctx.repo_root),与 closed_label_reconciler/wakeup_runner
一致,心跳文件名匹配 restart 助手期待的 patrol_inspector_daemon.ts。



* 修复 publish-gap 残留层:duplicate-marker log 读 companion artifact + 取代 superseded spawn intent

层2 残留:implement worker 把 IMPLEMENT_DONE:issue-N:ok 在 log 里 echo 多次→
worker_markers 返回 duplicate_or_conflicting_log_marker fail-closed→classifier 当
markerless 且不查 companion artifact→无 completed-marker action→无 publish→stale
harness-spawn-intent:dispatch-consensus-implementation:N 残留致 pending_implement_intent。

修:(1) classify_implement_attempt / completed_marker_actions 遇 duplicate marker 时
narrow 读 companion .refactor-loop/runs/implement-*.md(仅 implement log,仅末 30 行恰好
1 个 IMPLEMENT_DONE:ok 才接受);(2) suppress_publish_superseded_implementation_spawn_intents:
仅当某 issue 已有 executable publish_implementation_output 才把对应 dispatch-consensus-
implementation spawn intent 抑制为 status_only(implementation_ready_to_publish)。
不重蹈 #507 死锁:只在 publish 已 ready 后抑制 spawn(不漏派)、publish 仍全验证(不提前/
重复)、wakeup-runner/publish 授权口径不变。live 验证 #553 现投影 executable publish。



* 实现 issue #555 (#557)

* 修复 publish-gap 第3层:wakeup_runner clean_exit revalidation 对 duplicate-marker log 复用 artifact-fallback

pubgap2 修了 plan 侧 duplicate-marker artifact-fallback,但 wakeup_runner 的
_source_log_has_clean_marker(clean_exit_source_marker 预条件 revalidation)仍用严格
reader,对 #553 duplicate IMPLEMENT_DONE echo 返回 clean_exit_marker_missing→阻 publish。
改为严格 reader 优先,仅当 duplicate_or_conflicting_log_marker + is_implement_log +
_implement_run_artifact_done_marker 精确匹配 projected marker 才 fallback。复用 plan 侧
同一 helper,不弱化安全门(reviewer/release/rebase/非 implement/其它 fail reason 保持严格)。



* 实现 issue #553

* PR #561 review-fix output

* PR #561 remote-ci-fix output

* PR #561 review-fix output

* 收窄 restart daemon 权威到 owner-local 命令面 (#558)

* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。



* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。



* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。



* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。



* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。



* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+co…

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant